From 11bfc1ca74e3dbc02e926500228d19d9de2d82a1 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 21 Mar 2018 17:40:14 -0300 Subject: [PATCH 001/174] Add Goto as splash screen in android --- android/app/build.gradle | 7 ++ android/app/src/main/AndroidManifest.xml | 9 ++ .../hifiinterface/GotoActivity.java | 111 ++++++++++++++++++ .../hifiinterface/InterfaceActivity.java | 10 +- .../hifiinterface/PermissionChecker.java | 2 +- .../hifiinterface/view/DomainAdapter.java | 88 ++++++++++++++ .../app/src/main/res/drawable/ic_bookmark.xml | 4 + android/app/src/main/res/drawable/ic_menu.xml | 9 ++ .../app/src/main/res/drawable/ic_person.xml | 5 + .../app/src/main/res/drawable/ic_share.xml | 4 + android/app/src/main/res/font/raleway.ttf | Bin 0 -> 178520 bytes .../src/main/res/font/raleway_semibold.xml | 7 ++ .../app/src/main/res/layout/activity_goto.xml | 38 ++++++ .../app/src/main/res/layout/content_goto.xml | 69 +++++++++++ .../app/src/main/res/layout/domain_view.xml | 76 ++++++++++++ android/app/src/main/res/menu/menu_goto.xml | 10 ++ android/app/src/main/res/values/colors.xml | 6 + .../app/src/main/res/values/font_certs.xml | 17 +++ .../src/main/res/values/preloaded_fonts.xml | 6 + android/app/src/main/res/values/strings.xml | 5 + android/app/src/main/res/values/styles.xml | 18 +-- interface/src/Application.cpp | 7 +- libraries/networking/src/AddressManager.cpp | 2 - 23 files changed, 495 insertions(+), 15 deletions(-) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/view/DomainAdapter.java create mode 100644 android/app/src/main/res/drawable/ic_bookmark.xml create mode 100644 android/app/src/main/res/drawable/ic_menu.xml create mode 100644 android/app/src/main/res/drawable/ic_person.xml create mode 100644 android/app/src/main/res/drawable/ic_share.xml create mode 100644 android/app/src/main/res/font/raleway.ttf create mode 100644 android/app/src/main/res/font/raleway_semibold.xml create mode 100644 android/app/src/main/res/layout/activity_goto.xml create mode 100644 android/app/src/main/res/layout/content_goto.xml create mode 100644 android/app/src/main/res/layout/domain_view.xml create mode 100644 android/app/src/main/res/menu/menu_goto.xml create mode 100644 android/app/src/main/res/values/font_certs.xml create mode 100644 android/app/src/main/res/values/preloaded_fonts.xml diff --git a/android/app/build.gradle b/android/app/build.gradle index 97267258e2..7a6f34b58b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,6 +98,13 @@ android { dependencies { implementation 'com.google.vr:sdk-audio:1.80.0' implementation 'com.google.vr:sdk-base:1.80.0' + + + implementation 'com.android.support.constraint:constraint-layout:1.0.2' + implementation 'com.android.support:design:26.1.0' + implementation 'com.android.support:appcompat-v7:26.1.0' + compile 'com.android.support:recyclerview-v7:26.1.0' + implementation fileTree(include: ['*.jar'], dir: 'libs') } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b3a8c87649..f626334dbd 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -38,6 +38,11 @@ --> + + + + diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java new file mode 100644 index 0000000000..978ce80573 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -0,0 +1,111 @@ +package io.highfidelity.hifiinterface; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.TabHost; +import android.widget.TabWidget; +import android.widget.TextView; +import android.widget.Toast; + +import io.highfidelity.hifiinterface.view.DomainAdapter; + +public class GotoActivity extends AppCompatActivity { + + private DomainAdapter domainAdapter; + private DrawerLayout mDrawerLayout; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_goto); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + ActionBar actionbar = getSupportActionBar(); + actionbar.setDisplayHomeAsUpEnabled(true); + actionbar.setHomeAsUpIndicator(R.drawable.ic_menu); + + mDrawerLayout = findViewById(R.id.drawer_layout); + + TabHost tabs=(TabHost)findViewById(R.id.tabhost); + tabs.setup(); + + TabHost.TabSpec spec=tabs.newTabSpec("featured"); + spec.setContent(R.id.featured); + spec.setIndicator(getString(R.string.featured)); + tabs.addTab(spec); + + spec=tabs.newTabSpec("popular"); + spec.setContent(R.id.popular); + spec.setIndicator(getString(R.string.popular)); + tabs.addTab(spec); + + spec=tabs.newTabSpec("bookmarks"); + spec.setContent(R.id.bookmarks); + spec.setIndicator(getString(R.string.bookmarks)); + tabs.addTab(spec); + + tabs.setCurrentTab(0); + + TabWidget tabwidget=tabs.getTabWidget(); + for(int i=0;i { + + private Context mContext; + private LayoutInflater mInflater; + private ItemClickListener mClickListener; + + public DomainAdapter(Context c) { + mContext = c; + this.mInflater = LayoutInflater.from(mContext); + } + + public class Domain { + public String name; + public String url; + public Integer thumbnail; + Domain(String name, String url, Integer thumbnail) { + this.name = name; + this.thumbnail = thumbnail; + this.url = url; + } + } + + // references to our domains + private Domain[] mDomains = { + new Domain("Dev-master-mobile", "hifi://Dev-master-mobile", 0), + new Domain("Pikachu", "hifi://pikachu", 0), + }; + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = mInflater.inflate(R.layout.domain_view, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + // TODO + //holder.thumbnail.setImageResource(mDomains[position].thumbnail); + holder.mDomainName.setText(mDomains[position].name); + } + + @Override + public int getItemCount() { + return mDomains.length; + } + + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView mDomainName; + ImageView mThumbnail; + + ViewHolder(View itemView) { + super(itemView); + mThumbnail = (ImageView) itemView.findViewById(R.id.domainThumbnail); + mDomainName = (TextView) itemView.findViewById(R.id.domainName); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + int position = getAdapterPosition(); + if (mClickListener != null) mClickListener.onItemClick(view, position, mDomains[position]); + } + } + + // allows clicks events to be caught + public void setClickListener(ItemClickListener itemClickListener) { + this.mClickListener = itemClickListener; + } + // parent activity will implement this method to respond to click events + public interface ItemClickListener { + void onItemClick(View view, int position, Domain domain); + } +} diff --git a/android/app/src/main/res/drawable/ic_bookmark.xml b/android/app/src/main/res/drawable/ic_bookmark.xml new file mode 100644 index 0000000000..ddf03e340b --- /dev/null +++ b/android/app/src/main/res/drawable/ic_bookmark.xml @@ -0,0 +1,4 @@ + + + diff --git a/android/app/src/main/res/drawable/ic_menu.xml b/android/app/src/main/res/drawable/ic_menu.xml new file mode 100644 index 0000000000..cf37e2a393 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_menu.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/app/src/main/res/drawable/ic_person.xml b/android/app/src/main/res/drawable/ic_person.xml new file mode 100644 index 0000000000..cf57059c77 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_person.xml @@ -0,0 +1,5 @@ + + + + diff --git a/android/app/src/main/res/drawable/ic_share.xml b/android/app/src/main/res/drawable/ic_share.xml new file mode 100644 index 0000000000..91b01694da --- /dev/null +++ b/android/app/src/main/res/drawable/ic_share.xml @@ -0,0 +1,4 @@ + + + diff --git a/android/app/src/main/res/font/raleway.ttf b/android/app/src/main/res/font/raleway.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e570a2d5c39b2841b5753350a3822bd2b685e771 GIT binary patch literal 178520 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 + + diff --git a/android/app/src/main/res/layout/activity_goto.xml b/android/app/src/main/res/layout/activity_goto.xml new file mode 100644 index 0000000000..ab0fd69a74 --- /dev/null +++ b/android/app/src/main/res/layout/activity_goto.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/content_goto.xml b/android/app/src/main/res/layout/content_goto.xml new file mode 100644 index 0000000000..ee8acc8748 --- /dev/null +++ b/android/app/src/main/res/layout/content_goto.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/domain_view.xml b/android/app/src/main/res/layout/domain_view.xml new file mode 100644 index 0000000000..47028856d6 --- /dev/null +++ b/android/app/src/main/res/layout/domain_view.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/menu/menu_goto.xml b/android/app/src/main/res/menu/menu_goto.xml new file mode 100644 index 0000000000..41bbf6452e --- /dev/null +++ b/android/app/src/main/res/menu/menu_goto.xml @@ -0,0 +1,10 @@ + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 344907f039..9ed5686d3c 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,4 +1,10 @@ #ffffff + #272727 + #303F9F + #54D7FD + #1EB5EC + #333333 + #4F4F4F diff --git a/android/app/src/main/res/values/font_certs.xml b/android/app/src/main/res/values/font_certs.xml new file mode 100644 index 0000000000..d2226ac01c --- /dev/null +++ b/android/app/src/main/res/values/font_certs.xml @@ -0,0 +1,17 @@ + + + + @array/com_google_android_gms_fonts_certs_dev + @array/com_google_android_gms_fonts_certs_prod + + + + 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 + + + diff --git a/android/app/src/main/res/values/preloaded_fonts.xml b/android/app/src/main/res/values/preloaded_fonts.xml new file mode 100644 index 0000000000..82bcb6c19f --- /dev/null +++ b/android/app/src/main/res/values/preloaded_fonts.xml @@ -0,0 +1,6 @@ + + + + @font/raleway_semibold + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index b8080fae0f..f618fe805d 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,8 +1,13 @@ Interface + Go To Open in browser Share link Shared a link Share link + FEATURED + POPULAR + BOOKMARKS + Settings diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 23fe67f029..31fcbd8350 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,16 +1,20 @@ - + + + + + + + + \ No newline at end of file + + + + + + + + + + + diff --git a/interface/resources/icons/+android/myview-a.svg b/interface/resources/icons/+android/myview-a.svg index 307b559c95..9964678074 100755 --- a/interface/resources/icons/+android/myview-a.svg +++ b/interface/resources/icons/+android/myview-a.svg @@ -1,56 +1,19 @@ - - - -image/svg+xmlAsset 3 \ No newline at end of file + + + + + + + + + + + diff --git a/interface/resources/qml/hifi/+android/ActionBar.qml b/interface/resources/qml/hifi/+android/ActionBar.qml new file mode 100644 index 0000000000..7152c829bc --- /dev/null +++ b/interface/resources/qml/hifi/+android/ActionBar.qml @@ -0,0 +1,71 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls +import ".." + +Item { + id: actionBar + x:0 + y:0 + width: 300 + height: 300 + z: -1 + + signal sendToScript(var message); + signal windowClosed(); + + property bool shown: true + + onShownChanged: { + actionBar.visible = shown; + } + + Rectangle { + anchors.fill : parent + color: "transparent" + Flow { + id: flowMain + spacing: 10 + flow: Flow.TopToBottom + layoutDirection: Flow.TopToBottom + anchors.fill: parent + anchors.margins: 4 + } + } + + Component.onCompleted: { + // put on bottom + x = 50; + y = 0; + width = 300; + height = 300; + } + + function addButton(properties) { + var component = Qt.createComponent("button.qml"); + if (component.status == Component.Ready) { + var button = component.createObject(flowMain); + // copy all properites to button + var keys = Object.keys(properties).forEach(function (key) { + button[key] = properties[key]; + }); + return button; + } else if( component.status == Component.Error) { + console.log("Load button errors " + component.errorString()); + } + } + + function urlHelper(src) { + if (src.match(/\bhttp/)) { + return src; + } else { + return "../../../" + src; + } + } + +} diff --git a/interface/resources/qml/hifi/+android/AudioBar.qml b/interface/resources/qml/hifi/+android/AudioBar.qml index f524595ef5..a6d4e28813 100644 --- a/interface/resources/qml/hifi/+android/AudioBar.qml +++ b/interface/resources/qml/hifi/+android/AudioBar.qml @@ -40,7 +40,7 @@ Item { Component.onCompleted: { // put on bottom - x = 0; + x = parent.width-300; y = 0; width = 300; height = 300; diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml index fe71314ece..451921f155 100644 --- a/interface/resources/qml/hifi/+android/modesbar.qml +++ b/interface/resources/qml/hifi/+android/modesbar.qml @@ -10,7 +10,7 @@ import ".." Item { id: modesbar - y:60 + y:20 Rectangle { anchors.fill : parent color: "transparent" @@ -25,9 +25,9 @@ Item { } Component.onCompleted: { - width = 300 + 30; // That 30 is extra regardless the qty of items shown - height = 300 + 30; - x=Window.innerWidth - width; + width = 300; // That 30 is extra regardless the qty of items shown + height = 300; + x=parent.width - 540; } function addButton(properties) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e943157954..80775e1930 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -242,6 +242,7 @@ extern "C" { #if defined(Q_OS_ANDROID) #include +#include #endif enum ApplicationEvent { @@ -7870,7 +7871,8 @@ void Application::saveNextPhysicsStats(QString filename) { void Application::openAndroidActivity(const QString& activityName) { #if defined(Q_OS_ANDROID) - getActiveDisplayPlugin()->deactivate(); + qDebug() << "[Background-HIFI] Application::openAndroidActivity"; + //getActiveDisplayPlugin()->deactivate(); AndroidHelper::instance().requestActivity(activityName); connect(&AndroidHelper::instance(), &AndroidHelper::backFromAndroidActivity, this, &Application::restoreAfterAndroidActivity); #endif @@ -7878,11 +7880,63 @@ void Application::openAndroidActivity(const QString& activityName) { void Application::restoreAfterAndroidActivity() { #if defined(Q_OS_ANDROID) - if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { + qDebug() << "[Background-HIFI] restoreAfterAndroidActivity: this wouldn't be needed"; + + /*if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { qWarning() << "Could not re-activate display plugin"; - } + }*/ disconnect(&AndroidHelper::instance(), &AndroidHelper::backFromAndroidActivity, this, &Application::restoreAfterAndroidActivity); #endif } +#if defined(Q_OS_ANDROID) +void Application::enterBackground() { + qDebug() << "[Background-HIFI] enterBackground begin"; + QMetaObject::invokeMethod(DependencyManager::get().data(), + "stop", Qt::BlockingQueuedConnection); + qDebug() << "[Background-HIFI] deactivating display plugin"; + getActiveDisplayPlugin()->deactivate(); + qDebug() << "[Background-HIFI] enterBackground end"; +} +void Application::enterForeground() { + qDebug() << "[Background-HIFI] enterForeground qApp?" << (qApp?"yeah":"false"); + if (qApp && DependencyManager::isSet()) { + qDebug() << "[Background-HIFI] audioclient.start()"; + QMetaObject::invokeMethod(DependencyManager::get().data(), + "start", Qt::BlockingQueuedConnection); + } else { + qDebug() << "[Background-HIFI] audioclient.start() not done"; + } + if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { + qWarning() << "[Background-HIFI] Could not re-activate display plugin"; + } + +} + +extern "C" { + + +JNIEXPORT void +Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterBackground(JNIEnv *env, jobject obj) { + qDebug() << "[Background-HIFI] nativeEnterBackground"; + if (qApp) { + qDebug() << "[Background-HIFI] nativeEnterBackground begin (qApp)"; + qApp->enterBackground(); + } +} + +JNIEXPORT void +Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterForeground(JNIEnv *env, jobject obj) { + qDebug() << "[Background-HIFI] nativeEnterForeground"; + if (qApp) { + qDebug() << "[Background-HIFI] nativeEnterForeground begin (qApp)"; + qApp->enterForeground(); + } +} + + +} + +#endif + #include "Application.moc" diff --git a/interface/src/Application.h b/interface/src/Application.h index ab55861930..ec49aa055f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -292,6 +292,11 @@ public: void replaceDomainContent(const QString& url); +#if defined(Q_OS_ANDROID) + void enterBackground(); + void enterForeground(); +#endif + signals: void svoImportRequested(const QString& url); diff --git a/scripts/+android/defaultScripts.js b/scripts/+android/defaultScripts.js index 11aee6a9d2..98fbb4b1a7 100644 --- a/scripts/+android/defaultScripts.js +++ b/scripts/+android/defaultScripts.js @@ -14,7 +14,7 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/progress.js", "system/+android/touchscreenvirtualpad.js", - "system/+android/bottombar.js", + "system/+android/actionbar.js", "system/+android/audio.js" , "system/+android/modes.js", "system/+android/stats.js"/*, diff --git a/scripts/system/+android/actionbar.js b/scripts/system/+android/actionbar.js new file mode 100644 index 0000000000..9aed1e6cf9 --- /dev/null +++ b/scripts/system/+android/actionbar.js @@ -0,0 +1,53 @@ +"use strict"; +// +// backbutton.js +// scripts/system/+android +// +// Created by Gabriel Calero & Cristian Duarte on Apr 06, 2018 +// 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 +// +(function() { // BEGIN LOCAL_SCOPE + +var actionbar; +var backButton; + +var logEnabled = true; + +function printd(str) { + if (logEnabled) + print("[actionbar.js] " + str); +} + +function init() { + actionbar = new QmlFragment({ + qml: "hifi/ActionBar.qml" + }); + backButton = actionbar.addButton({ + icon: "icons/+android/backward.svg", + activeIcon: "icons/+android/backward.svg", + text: "", + bgOpacity: 0.0, + activeBgOpacity: 0.0, + bgColor: "#FFFFFF" + }); + + backButton.clicked.connect(onBackPressed); +} + +function onBackPressed() { + App.openAndroidActivity("Goto"); +} + + +Script.scriptEnding.connect(function () { + if(backButton) { + backButton.clicked.disconnect(onBackPressed); + } +}); + +init(); + +}()); // END LOCAL_SCOPE From 8010fd2420f5e05dce90b543a23db9fb3262a17a Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 11 Apr 2018 18:43:39 -0300 Subject: [PATCH 012/174] New view selector behaviour. Update icons --- .../resources/icons/+android/backward.svg | 10 +- .../resources/icons/+android/mic-unmute-a.svg | 92 +++-------- .../resources/icons/+android/myview-a.svg | 12 +- .../resources/icons/+android/radar-a.svg | 1 - .../resources/icons/+android/radar-hover.svg | 1 - .../resources/icons/+android/radar-i.svg | 1 - interface/resources/images/fly.png | Bin 11088 -> 8688 bytes .../resources/qml/hifi/+android/modesbar.qml | 26 +-- scripts/system/+android/modes.js | 156 ++++-------------- 9 files changed, 74 insertions(+), 225 deletions(-) mode change 100644 => 100755 interface/resources/icons/+android/mic-unmute-a.svg delete mode 100755 interface/resources/icons/+android/radar-a.svg delete mode 100755 interface/resources/icons/+android/radar-hover.svg delete mode 100755 interface/resources/icons/+android/radar-i.svg diff --git a/interface/resources/icons/+android/backward.svg b/interface/resources/icons/+android/backward.svg index ad102b886e..6b4c560768 100755 --- a/interface/resources/icons/+android/backward.svg +++ b/interface/resources/icons/+android/backward.svg @@ -3,13 +3,11 @@ - - - - + diff --git a/interface/resources/icons/+android/mic-unmute-a.svg b/interface/resources/icons/+android/mic-unmute-a.svg old mode 100644 new mode 100755 index bb28dc0f2b..8717636a34 --- a/interface/resources/icons/+android/mic-unmute-a.svg +++ b/interface/resources/icons/+android/mic-unmute-a.svg @@ -1,70 +1,22 @@ - - - -image/svg+xml \ No newline at end of file + + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/myview-a.svg b/interface/resources/icons/+android/myview-a.svg index 9964678074..f8becb3850 100755 --- a/interface/resources/icons/+android/myview-a.svg +++ b/interface/resources/icons/+android/myview-a.svg @@ -3,17 +3,17 @@ - - + C49.4,25.9,49.5,24.2,48.1,22.6z M46.4,27.2C41,34.1,33.9,38.1,26.2,38.6c-7.3-0.1-12.6-2.4-17.4-6c-2.2-1.6-4.1-3.5-5.6-5.8 + c-0.7-1-0.9-2-0.1-3.1c4.8-7.1,16.4-14.6,28.2-11.1c6.2,1.9,11.3,5.3,15.2,10.5C47.8,24.8,47.8,25.4,46.4,27.2z"/> + diff --git a/interface/resources/icons/+android/radar-a.svg b/interface/resources/icons/+android/radar-a.svg deleted file mode 100755 index e4b157f827..0000000000 --- a/interface/resources/icons/+android/radar-a.svg +++ /dev/null @@ -1 +0,0 @@ -Asset 1 \ No newline at end of file diff --git a/interface/resources/icons/+android/radar-hover.svg b/interface/resources/icons/+android/radar-hover.svg deleted file mode 100755 index e4b157f827..0000000000 --- a/interface/resources/icons/+android/radar-hover.svg +++ /dev/null @@ -1 +0,0 @@ -Asset 1 \ No newline at end of file diff --git a/interface/resources/icons/+android/radar-i.svg b/interface/resources/icons/+android/radar-i.svg deleted file mode 100755 index 3994a775d3..0000000000 --- a/interface/resources/icons/+android/radar-i.svg +++ /dev/null @@ -1 +0,0 @@ -Asset 1 \ No newline at end of file diff --git a/interface/resources/images/fly.png b/interface/resources/images/fly.png index 0edfcab21bbe3f78c684a004a00d5c7ce7c5a3fe..02f72d568983840d96ee85c8fdc13775fac26919 100644 GIT binary patch literal 8688 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 diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml index 451921f155..642703017f 100644 --- a/interface/resources/qml/hifi/+android/modesbar.qml +++ b/interface/resources/qml/hifi/+android/modesbar.qml @@ -11,18 +11,6 @@ import ".." Item { id: modesbar y:20 - Rectangle { - anchors.fill : parent - color: "transparent" - Flow { - id: flowMain - spacing: 0 - flow: Flow.TopToBottom - layoutDirection: Flow.TopToBottom - anchors.fill: parent - anchors.margins: 4 - } - } Component.onCompleted: { width = 300; // That 30 is extra regardless the qty of items shown @@ -35,7 +23,7 @@ Item { console.log("load button"); if (component.status == Component.Ready) { console.log("load button 2"); - var button = component.createObject(flowMain); + var button = component.createObject(modesbar); // copy all properites to button var keys = Object.keys(properties).forEach(function (key) { button[key] = properties[key]; @@ -59,14 +47,12 @@ Item { function fromScript(message) { switch (message.type) { - case "allButtonsShown": - modesbar.height = flowMain.children.length * 300 + 30; // That 30 is extra regardless the qty of items shown - break; - case "inactiveButtonsHidden": - modesbar.height = 300 + 30; - break; + case "switch": + // message.params.to + // still not needed + break; default: - break; + break; } } diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js index c41ae1f327..a7c1060ffb 100644 --- a/scripts/system/+android/modes.js +++ b/scripts/system/+android/modes.js @@ -11,15 +11,21 @@ // (function() { // BEGIN LOCAL_SCOPE -var modesbar; -var modesButtons; -var currentSelectedBtn; +var modeButton; +var currentMode; +var barQml; var SETTING_CURRENT_MODE_KEY = 'Android/Mode'; var MODE_VR = "VR", MODE_RADAR = "RADAR", MODE_MY_VIEW = "MY VIEW"; var DEFAULT_MODE = MODE_MY_VIEW; -var logEnabled = true; +var nextMode = {}; +nextMode[MODE_RADAR]=MODE_MY_VIEW; +nextMode[MODE_MY_VIEW]=MODE_RADAR; +var modeLabel = {}; +modeLabel[MODE_RADAR]="TOP VIEW"; +modeLabel[MODE_MY_VIEW]="MY VIEW"; +var logEnabled = false; var radar = Script.require('./radar.js'); var uniqueColor = Script.require('./uniqueColor.js'); @@ -32,87 +38,30 @@ function printd(str) { function init() { radar.setUniqueColor(uniqueColor); radar.init(); - setupModesBar(); -} - -function shutdown() { - -} - -function setupModesBar() { - - var bar = new QmlFragment({ + + barQml = new QmlFragment({ qml: "hifi/modesbar.qml" }); - var buttonRadarMode = bar.addButton({ - icon: "icons/radar-i.svg", - activeIcon: "icons/radar-a.svg", - hoverIcon: "icons/radar-a.svg", + modeButton = barQml.addButton({ + icon: "icons/myview-a.svg", activeBgOpacity: 0.0, hoverBgOpacity: 0.0, activeHoverBgOpacity: 0.0, - text: "RADAR", + text: "MODE", height:240, bottomMargin: 6, textSize: 45 }); - var buttonMyViewMode = bar.addButton({ - icon: "icons/myview-i.svg", - activeIcon: "icons/myview-a.svg", - hoverIcon: "icons/myview-a.svg", - activeBgOpacity: 0.0, - hoverBgOpacity: 0.0, - activeHoverBgOpacity: 0.0, - text: "MY VIEW", - height: 240, - bottomMargin: 6, - textSize: 45 - }); - modesButtons = [buttonRadarMode, buttonMyViewMode]; + switchToMode(getCurrentModeSetting()); - var mode = getCurrentModeSetting(); - - var buttonsRevealed = false; - bar.sendToQml({type: "inactiveButtonsHidden"}); - - modesbar = { - restoreMyViewButton: function() { - switchModeButtons(buttonMyViewMode); - saveCurrentModeSetting(MODE_MY_VIEW); - }, - sendToQml: function(o) { bar.sendToQml(o); }, - qmlFragment: bar - }; - - buttonRadarMode.clicked.connect(function() { - //if (connections.isVisible()) return; - saveCurrentModeSetting(MODE_RADAR); - printd("Radar clicked"); - onButtonClicked(buttonRadarMode, function() { - radar.startRadarMode(); - }); - }); - buttonMyViewMode.clicked.connect(function() { - //if (connections.isVisible()) return; - saveCurrentModeSetting(MODE_MY_VIEW); - printd("My View clicked"); - onButtonClicked(buttonMyViewMode, function() { - if (currentSelectedBtn == buttonRadarMode) { - radar.endRadarMode(); - } - }); + modeButton.clicked.connect(function() { + switchToMode(nextMode[currentMode]); }); +} - var savedButton; - if (mode == MODE_MY_VIEW) { - savedButton = buttonMyViewMode; - } else { - savedButton = buttonRadarMode; - } - printd("[MODE] previous mode " + mode); +function shutdown() { - savedButton.clicked(); } function saveCurrentModeSetting(mode) { @@ -123,62 +72,29 @@ function getCurrentModeSetting(mode) { return Settings.getValue(SETTING_CURRENT_MODE_KEY, DEFAULT_MODE); } -function showAllButtons() { - for (var i=0; i Date: Wed, 11 Apr 2018 19:33:43 -0300 Subject: [PATCH 013/174] Move jump button to the right. Adjust position of buttons --- android/app/src/main/res/values/strings.xml | 2 +- interface/resources/qml/hifi/+android/ActionBar.qml | 2 +- interface/resources/qml/hifi/+android/AudioBar.qml | 4 ++-- interface/resources/qml/hifi/+android/modesbar.qml | 2 +- .../src/input-plugins/TouchscreenVirtualPadDevice.cpp | 5 +++-- libraries/ui/src/VirtualPadManager.cpp | 4 ++-- libraries/ui/src/VirtualPadManager.h | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index f618fe805d..8f2d043f8d 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ Interface - Go To + Home Open in browser Share link Shared a link diff --git a/interface/resources/qml/hifi/+android/ActionBar.qml b/interface/resources/qml/hifi/+android/ActionBar.qml index 7152c829bc..3bc4785e02 100644 --- a/interface/resources/qml/hifi/+android/ActionBar.qml +++ b/interface/resources/qml/hifi/+android/ActionBar.qml @@ -40,7 +40,7 @@ Item { Component.onCompleted: { // put on bottom - x = 50; + x = 30; y = 0; width = 300; height = 300; diff --git a/interface/resources/qml/hifi/+android/AudioBar.qml b/interface/resources/qml/hifi/+android/AudioBar.qml index a6d4e28813..0480d4ee4f 100644 --- a/interface/resources/qml/hifi/+android/AudioBar.qml +++ b/interface/resources/qml/hifi/+android/AudioBar.qml @@ -40,8 +40,8 @@ Item { Component.onCompleted: { // put on bottom - x = parent.width-300; - y = 0; + x = parent.width-315; + y = 5; width = 300; height = 300; } diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml index 642703017f..7736c589a1 100644 --- a/interface/resources/qml/hifi/+android/modesbar.qml +++ b/interface/resources/qml/hifi/+android/modesbar.qml @@ -15,7 +15,7 @@ Item { Component.onCompleted: { width = 300; // That 30 is extra regardless the qty of items shown height = 300; - x=parent.width - 540; + x=parent.width - 555; } function addButton(properties) { diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 957104bd30..0f3002b8c1 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -80,9 +80,10 @@ void TouchscreenVirtualPadDevice::setupControlsPositions(VirtualPad::Manager& vi virtualPadManager.getLeftVirtualPad()->setFirstTouch(_moveRefTouchPoint); // Jump button - float leftMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_LEFT_MARGIN_PIXELS / VirtualPad::Manager::DPI; + float jumpBtnPixelSize = _screenDPI * VirtualPad::Manager::JUMP_BTN_FULL_PIXELS / VirtualPad::Manager::DPI; + float rightMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_RIGHT_MARGIN_PIXELS / VirtualPad::Manager::DPI; float bottomMargin = _screenDPI * VirtualPad::Manager::JUMP_BTN_BOTTOM_MARGIN_PIXELS/ VirtualPad::Manager::DPI; - _jumpButtonPosition = glm::vec2( _jumpButtonRadius + leftMargin, eventScreen->size().height() - bottomMargin - _jumpButtonRadius - _extraBottomMargin); + _jumpButtonPosition = glm::vec2( eventScreen->size().width() - rightMargin - jumpBtnPixelSize, eventScreen->size().height() - bottomMargin - _jumpButtonRadius - _extraBottomMargin); virtualPadManager.setJumpButtonPosition(_jumpButtonPosition); } diff --git a/libraries/ui/src/VirtualPadManager.cpp b/libraries/ui/src/VirtualPadManager.cpp index c786110bdf..1c76672827 100644 --- a/libraries/ui/src/VirtualPadManager.cpp +++ b/libraries/ui/src/VirtualPadManager.cpp @@ -39,9 +39,9 @@ namespace VirtualPad { const float Manager::BASE_MARGIN_PIXELS = 59.0f; const float Manager::STICK_RADIUS_PIXELS = 105.0f; const float Manager::JUMP_BTN_TRIMMED_RADIUS_PIXELS = 67.0f; - const float Manager::JUMP_BTN_FULL_PIXELS = 134.0f; + const float Manager::JUMP_BTN_FULL_PIXELS = 164.0f; const float Manager::JUMP_BTN_BOTTOM_MARGIN_PIXELS = 67.0f; - const float Manager::JUMP_BTN_LEFT_MARGIN_PIXELS = 547.0f; + const float Manager::JUMP_BTN_RIGHT_MARGIN_PIXELS = 20.0f; Manager::Manager() { diff --git a/libraries/ui/src/VirtualPadManager.h b/libraries/ui/src/VirtualPadManager.h index 68b3d4f10f..6f7fbcc921 100644 --- a/libraries/ui/src/VirtualPadManager.h +++ b/libraries/ui/src/VirtualPadManager.h @@ -54,7 +54,7 @@ namespace VirtualPad { static const float JUMP_BTN_TRIMMED_RADIUS_PIXELS; static const float JUMP_BTN_FULL_PIXELS; static const float JUMP_BTN_BOTTOM_MARGIN_PIXELS; - static const float JUMP_BTN_LEFT_MARGIN_PIXELS; + static const float JUMP_BTN_RIGHT_MARGIN_PIXELS; private: Instance _leftVPadInstance; From a7328f09347785d68914602e20a0d858053d7381 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Thu, 12 Apr 2018 15:55:20 -0300 Subject: [PATCH 014/174] Fix View not attached to windown manager crash when starting the app in landscape mode on Pixel XL --- .../java/io/highfidelity/hifiinterface/GotoActivity.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index dc07c7b99a..4265201946 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -174,4 +174,10 @@ public class GotoActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } + + @Override + protected void onDestroy() { + cancelActivityIndicator(); + super.onDestroy(); + } } From 0f39ab0bb92eadef009e2f293238ed25d4614590 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Thu, 12 Apr 2018 17:47:58 -0300 Subject: [PATCH 015/174] Android GotoAcitivity is now HomeActivity (leaving the place for the upcoming 'Go To activity' itself --- android/app/src/main/AndroidManifest.xml | 2 +- .../{GotoActivity.java => HomeActivity.java} | 14 +++++++------- .../hifiinterface/InterfaceActivity.java | 4 ++-- .../hifiinterface/PermissionChecker.java | 4 ++-- .../{activity_goto.xml => activity_home.xml} | 4 ++-- .../layout/{content_goto.xml => content_home.xml} | 4 ++-- .../main/res/menu/{menu_goto.xml => menu_home.xml} | 7 ++++++- android/app/src/main/res/values/strings.xml | 1 + android/app/src/main/res/values/styles.xml | 2 +- 9 files changed, 24 insertions(+), 18 deletions(-) rename android/app/src/main/java/io/highfidelity/hifiinterface/{GotoActivity.java => HomeActivity.java} (94%) rename android/app/src/main/res/layout/{activity_goto.xml => activity_home.xml} (93%) rename android/app/src/main/res/layout/{content_goto.xml => content_home.xml} (96%) rename android/app/src/main/res/menu/{menu_goto.xml => menu_home.xml} (60%) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index caea9c2939..c77caa20fb 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -39,7 +39,7 @@ --> diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java similarity index 94% rename from android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java rename to android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java index 4265201946..d69faec2e3 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java @@ -23,7 +23,7 @@ import android.widget.TextView; import io.highfidelity.hifiinterface.QtPreloader.QtPreloader; import io.highfidelity.hifiinterface.view.DomainAdapter; -public class GotoActivity extends AppCompatActivity { +public class HomeActivity extends AppCompatActivity { /** * Set this intent extra param to NOT start a new InterfaceActivity after a domain is selected" @@ -36,9 +36,9 @@ public class GotoActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_goto); + setContentView(R.layout.activity_home); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - toolbar.setTitleTextAppearance(this, R.style.GotoActionBarTitleStyle); + toolbar.setTitleTextAppearance(this, R.style.HomeActionBarTitleStyle); setSupportActionBar(toolbar); ActionBar actionbar = getSupportActionBar(); @@ -83,9 +83,9 @@ public class GotoActivity extends AppCompatActivity { @Override public void onItemClick(View view, int position, DomainAdapter.Domain domain) { - Intent intent = new Intent(GotoActivity.this, InterfaceActivity.class); + Intent intent = new Intent(HomeActivity.this, InterfaceActivity.class); intent.putExtra(InterfaceActivity.DOMAIN_URL, domain.url); - GotoActivity.this.finish(); + HomeActivity.this.finish(); if (getIntent() != null && getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) && getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { @@ -137,7 +137,7 @@ public class GotoActivity extends AppCompatActivity { preloadTask = new AsyncTask() { @Override protected Object doInBackground(Object[] objects) { - new QtPreloader(GotoActivity.this).initQt(); + new QtPreloader(HomeActivity.this).initQt(); runOnUiThread(new Runnable() { @Override public void run() { @@ -154,7 +154,7 @@ public class GotoActivity extends AppCompatActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - //getMenuInflater().inflate(R.menu.menu_goto, menu); + //getMenuInflater().inflate(R.menu.menu_home, menu); return true; } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index 812252663a..678f7e8aac 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -200,8 +200,8 @@ public class InterfaceActivity extends QtActivity { public void openGotoActivity(String activityName) { switch (activityName) { case "Goto": { - Intent intent = new Intent(this, GotoActivity.class); - intent.putExtra(GotoActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, true); + Intent intent = new Intent(this, HomeActivity.class); + intent.putExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, true); startActivity(intent); break; } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java b/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java index e52000f944..b1c5f570c8 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java @@ -11,7 +11,7 @@ import android.app.AlertDialog; import org.json.JSONException; import org.json.JSONObject; -import android.util.Log; + import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; @@ -64,7 +64,7 @@ public class PermissionChecker extends Activity { private void launchActivityWithPermissions(){ finish(); - Intent i = new Intent(this, GotoActivity.class); + Intent i = new Intent(this, HomeActivity.class); startActivity(i); finish(); } diff --git a/android/app/src/main/res/layout/activity_goto.xml b/android/app/src/main/res/layout/activity_home.xml similarity index 93% rename from android/app/src/main/res/layout/activity_goto.xml rename to android/app/src/main/res/layout/activity_home.xml index ab0fd69a74..144ca84a0f 100644 --- a/android/app/src/main/res/layout/activity_goto.xml +++ b/android/app/src/main/res/layout/activity_home.xml @@ -21,7 +21,7 @@ android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> - + @@ -32,7 +32,7 @@ android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" - app:menu="@menu/menu_goto" + app:menu="@menu/menu_home" /> diff --git a/android/app/src/main/res/layout/content_goto.xml b/android/app/src/main/res/layout/content_home.xml similarity index 96% rename from android/app/src/main/res/layout/content_goto.xml rename to android/app/src/main/res/layout/content_home.xml index 1e17fff07c..f25d9d8f7b 100644 --- a/android/app/src/main/res/layout/content_goto.xml +++ b/android/app/src/main/res/layout/content_home.xml @@ -5,8 +5,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" - tools:context="io.highfidelity.hifiinterface.GotoActivity" - tools:showIn="@layout/activity_goto"> + tools:context="io.highfidelity.hifiinterface.HomeActivity" + tools:showIn="@layout/activity_home"> + tools:context="io.highfidelity.hifiinterface.HomeActivity"> + POPULAR BOOKMARKS Settings + Go to diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cfa040837d..2058212651 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -16,7 +16,7 @@ - + - - - + + + diff --git a/interface/resources/images/fly.png b/interface/resources/images/fly.png index 02f72d568983840d96ee85c8fdc13775fac26919..b8b96645f8880f53c27505d4a3ee95d58d5ca337 100644 GIT binary patch literal 8137 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 literal 8688 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 Date: Thu, 12 Apr 2018 19:02:03 -0300 Subject: [PATCH 017/174] Hide jump button while moving. Fix jump button right alignment in pixel --- interface/src/Application.cpp | 3 ++ .../Basic2DWindowOpenGLDisplayPlugin.cpp | 29 ++++++++++--------- .../TouchscreenVirtualPadDevice.cpp | 18 ++++++++---- .../TouchscreenVirtualPadDevice.h | 1 + 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b68263ba4..8cba6b1220 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2626,6 +2626,9 @@ void Application::initializeUi() { offscreenUi->resume(); connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ resizeGL(); + if (_touchscreenVirtualPadDevice) { + _touchscreenVirtualPadDevice->resize(); + } }); // This will set up the input plugins UI diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index f33af1b580..59cd637ca0 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -147,20 +147,21 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); }); - - // render stick head - auto jumpTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getJumpButtonPosition(), - _virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize); - render([&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setProjectionTransform(mat4()); - batch.setPipeline(_cursorPipeline); - batch.setResourceTexture(0, _virtualPadJumpBtnTexture); - batch.resetViewTransform(); - batch.setModelTransform(jumpTransform); - batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); - batch.draw(gpu::TRIANGLE_STRIP, 4); - }); + if (!virtualPadManager.getLeftVirtualPad()->isBeingTouched()) { + // render stick head + auto jumpTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getJumpButtonPosition(), + _virtualPadJumpBtnPixelSize, _virtualPadJumpBtnPixelSize); + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_cursorPipeline); + batch.setResourceTexture(0, _virtualPadJumpBtnTexture); + batch.resetViewTransform(); + batch.setModelTransform(jumpTransform); + batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + } } #endif Parent::compositeExtra(); diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 0f3002b8c1..7ee2135325 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -43,6 +43,18 @@ void TouchscreenVirtualPadDevice::init() { _fixedPosition = true; // This should be config _viewTouchUpdateCount = 0; + resize(); + + auto& virtualPadManager = VirtualPad::Manager::instance(); + + if (_fixedPosition) { + virtualPadManager.getLeftVirtualPad()->setShown(virtualPadManager.isEnabled() && !virtualPadManager.isHidden()); // Show whenever it's enabled + } + + KeyboardMouseDevice::enableTouch(false); // Touch for view controls is managed by this plugin +} + +void TouchscreenVirtualPadDevice::resize() { QScreen* eventScreen = qApp->primaryScreen(); if (_screenDPIProvided != eventScreen->physicalDotsPerInch()) { _screenWidthCenter = eventScreen->size().width() / 2; @@ -59,12 +71,6 @@ void TouchscreenVirtualPadDevice::init() { auto& virtualPadManager = VirtualPad::Manager::instance(); setupControlsPositions(virtualPadManager, true); - - if (_fixedPosition) { - virtualPadManager.getLeftVirtualPad()->setShown(virtualPadManager.isEnabled() && !virtualPadManager.isHidden()); // Show whenever it's enabled - } - - KeyboardMouseDevice::enableTouch(false); // Touch for view controls is managed by this plugin } void TouchscreenVirtualPadDevice::setupControlsPositions(VirtualPad::Manager& virtualPadManager, bool force) { diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h index 212b7633ec..e7e540b503 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h @@ -26,6 +26,7 @@ public: // Plugin functions virtual void init() override; + virtual void resize(); virtual bool isSupported() const override; virtual const QString getName() const override { return NAME; } From dc3914d6eb1f770c8b5bfd8c3ec65f199d4821e5 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Thu, 12 Apr 2018 19:23:42 -0300 Subject: [PATCH 018/174] Android - new (empty) activity GotoActivity --- android/app/src/main/AndroidManifest.xml | 7 +++- .../hifiinterface/GotoActivity.java | 38 +++++++++++++++++++ .../hifiinterface/HomeActivity.java | 23 +++++++++-- .../app/src/main/res/layout/activity_goto.xml | 18 +++++++++ android/app/src/main/res/values/strings.xml | 5 ++- 5 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java create mode 100644 android/app/src/main/res/layout/activity_goto.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index c77caa20fb..ed9caee58b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -40,10 +40,15 @@ --> + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index d35b7e5bb2..f380f3cf6e 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ Interface - Home + Home + Go To Open in browser Share link Shared a link @@ -9,6 +10,6 @@ POPULAR BOOKMARKS Settings - Go to + Go To From 20acfdfb82b6ef88ca6a9a502362052c78c72cf0 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Thu, 12 Apr 2018 20:31:36 -0300 Subject: [PATCH 019/174] First Android Go To implementation (from the Home screen) --- .../hifiinterface/GotoActivity.java | 45 ++++++++++++++++++- .../app/src/main/res/layout/activity_goto.xml | 16 +++++++ android/app/src/main/res/values/strings.xml | 2 + 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index fbb4953ab3..62636b5ceb 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -1,14 +1,22 @@ package io.highfidelity.hifiinterface; +import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.NavUtils; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.AppCompatButton; import android.support.v7.widget.Toolbar; +import android.view.KeyEvent; import android.view.MenuItem; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; public class GotoActivity extends AppCompatActivity { + private EditText mUrlEditText; + private AppCompatButton mGoBtn; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -20,6 +28,41 @@ public class GotoActivity extends AppCompatActivity { ActionBar actionbar = getSupportActionBar(); actionbar.setDisplayHomeAsUpEnabled(true); + + mUrlEditText = (EditText) findViewById(R.id.url_text); + mUrlEditText.setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View view, int i, KeyEvent keyEvent) { + if (i == KeyEvent.KEYCODE_ENTER) { + actionGo(); + return true; + } + return false; + } + }); + mGoBtn = (AppCompatButton) findViewById(R.id.go_btn); + + mGoBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + actionGo(); + } + }); + } + + private void actionGo() { + String urlString = mUrlEditText.getText().toString(); + if (!urlString.trim().isEmpty()) { + Intent intent = new Intent(this, InterfaceActivity.class); + intent.putExtra(InterfaceActivity.DOMAIN_URL, urlString); + finish(); + if (getIntent() != null && + getIntent().hasExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY) && + getIntent().getBooleanExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + } + startActivity(intent); + } } @Override diff --git a/android/app/src/main/res/layout/activity_goto.xml b/android/app/src/main/res/layout/activity_goto.xml index a10426468e..e4ecda6157 100644 --- a/android/app/src/main/res/layout/activity_goto.xml +++ b/android/app/src/main/res/layout/activity_goto.xml @@ -15,4 +15,20 @@ app:layout_constraintTop_toTopOf="@id/root_activity_goto" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index f380f3cf6e..6ce0670dd8 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -11,5 +11,7 @@ BOOKMARKS Settings Go To + Type a domain url + Go From ffb38eb490c7760a5d38440c0607c370926db13b Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Thu, 12 Apr 2018 20:45:35 -0300 Subject: [PATCH 020/174] Add hifi scheme for scheme-less addresses --- .../io/highfidelity/hifiinterface/GotoActivity.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index 62636b5ceb..49208a8368 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -12,6 +12,9 @@ import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; +import java.net.URI; +import java.net.URISyntaxException; + public class GotoActivity extends AppCompatActivity { private EditText mUrlEditText; @@ -53,6 +56,16 @@ public class GotoActivity extends AppCompatActivity { private void actionGo() { String urlString = mUrlEditText.getText().toString(); if (!urlString.trim().isEmpty()) { + URI uri; + try { + uri = new URI(urlString); + } catch (URISyntaxException e) { + return; + } + if (uri.getScheme()==null || uri.getScheme().isEmpty()) { + urlString = "hifi://" + urlString; + } + Intent intent = new Intent(this, InterfaceActivity.class); intent.putExtra(InterfaceActivity.DOMAIN_URL, urlString); finish(); From 6b1e22c22698c2c9b76300089c69e0d4572d33c1 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Thu, 12 Apr 2018 20:53:17 -0300 Subject: [PATCH 021/174] Android Go To - Set inputType as textUri --- android/app/src/main/res/layout/activity_goto.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/res/layout/activity_goto.xml b/android/app/src/main/res/layout/activity_goto.xml index e4ecda6157..7f4e7d5fcf 100644 --- a/android/app/src/main/res/layout/activity_goto.xml +++ b/android/app/src/main/res/layout/activity_goto.xml @@ -20,7 +20,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/goto_url_hint" - android:inputType="text" + android:inputType="textUri" android:imeOptions="actionGo" app:layout_constraintTop_toBottomOf="@id/toolbar" /> From a073cba4d4bc357715f3f5a6419ab20487fe5090 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Fri, 13 Apr 2018 12:35:33 -0300 Subject: [PATCH 022/174] Set the current address as default in the Go To screen --- android/app/src/main/cpp/native.cpp | 22 ++++++++++++++++++ .../hifiinterface/GotoActivity.java | 3 +++ .../highfidelity/hifiinterface/HifiUtils.java | 23 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index aac55adf41..c71be76b3e 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -182,4 +182,26 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeGoBack AndroidHelper::instance().goBackFromAndroidActivity(); } +// HifiUtils +JNIEXPORT jstring JNICALL Java_io_highfidelity_hifiinterface_HifiUtils_getCurrentAddress(JNIEnv *env, jobject instance) { + QSharedPointer addressManager = DependencyManager::get(); + if (!addressManager) { + return env->NewString(nullptr, 0); + } + + QString str; + if (!addressManager->getPlaceName().isEmpty()) { + str = addressManager->getPlaceName(); + } else if (!addressManager->getHost().isEmpty()) { + str = addressManager->getHost(); + } + + QRegExp pathRegEx("(\\/[^\\/]+)"); + if (!addressManager->currentPath().isEmpty() && addressManager->currentPath().contains(pathRegEx) && pathRegEx.matchedLength() > 0) { + str += pathRegEx.cap(0); + } + + return env->NewStringUTF(str.toLatin1().data()); +} + } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index 49208a8368..65221bc21c 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -43,6 +43,9 @@ public class GotoActivity extends AppCompatActivity { return false; } }); + + mUrlEditText.setText(HifiUtils.getInstance().getCurrentAddress()); + mGoBtn = (AppCompatButton) findViewById(R.id.go_btn); mGoBtn.setOnClickListener(new View.OnClickListener() { diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java new file mode 100644 index 0000000000..15d716548f --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java @@ -0,0 +1,23 @@ +package io.highfidelity.hifiinterface; + +/** + * Created by Gabriel Calero & Cristian Duarte on 4/13/18. + */ + +public class HifiUtils { + + private static HifiUtils instance; + + private HifiUtils() { + } + + public static HifiUtils getInstance() { + if (instance == null) { + instance = new HifiUtils(); + } + return instance; + } + + public native String getCurrentAddress(); + +} From 2e1f2f4214eccf763294f18494a4ed69ef761091 Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Fri, 13 Apr 2018 14:30:55 -0300 Subject: [PATCH 023/174] Android Go To, minor visual adjustments --- android/app/src/main/res/layout/activity_goto.xml | 7 ++++++- android/app/src/main/res/values/colors.xml | 2 ++ android/app/src/main/res/values/dimens.xml | 2 ++ android/app/src/main/res/values/styles.xml | 6 ++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/res/layout/activity_goto.xml b/android/app/src/main/res/layout/activity_goto.xml index 7f4e7d5fcf..06e1383da5 100644 --- a/android/app/src/main/res/layout/activity_goto.xml +++ b/android/app/src/main/res/layout/activity_goto.xml @@ -19,6 +19,9 @@ android:id="@+id/url_text" android:layout_width="match_parent" android:layout_height="wrap_content" + style="@style/HifiEditText" + android:layout_marginStart="@dimen/activity_horizontal_margin" + android:layout_marginEnd="@dimen/activity_horizontal_margin" android:hint="@string/goto_url_hint" android:inputType="textUri" android:imeOptions="actionGo" @@ -28,7 +31,9 @@ android:id="@+id/go_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/button_horizontal_margin" android:text="@string/go" - app:layout_constraintTop_toBottomOf="@id/url_text"/> + app:layout_constraintTop_toBottomOf="@id/url_text" + app:layout_constraintEnd_toEndOf="@id/root_activity_goto"/> diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 731aff02d8..0325881f1b 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -8,4 +8,6 @@ #333333 #4F4F4F #33999999 + #212121 + #9e9e9e diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml index a9ec657aa9..440adcf6b9 100644 --- a/android/app/src/main/res/values/dimens.xml +++ b/android/app/src/main/res/values/dimens.xml @@ -9,4 +9,6 @@ 14dp 12dp + 12dp + 8dp \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 2058212651..55c9b2af11 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -48,5 +48,11 @@ @dimen/text_size_subtitle_material_toolbar + From b26bf30904e9ec58469ed8609fdd33b577ff79fc Mon Sep 17 00:00:00 2001 From: Cristian Luis Duarte Date: Fri, 13 Apr 2018 17:51:29 -0300 Subject: [PATCH 024/174] Android - Make HomeActivity responsible for opening Interface avoiding blank-screen crashes when entering domains more than once --- .../hifiinterface/GotoActivity.java | 13 +++---- .../hifiinterface/HomeActivity.java | 36 +++++++++++++------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index 65221bc21c..a83f93d080 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -17,6 +17,8 @@ import java.net.URISyntaxException; public class GotoActivity extends AppCompatActivity { + public static final String PARAM_DOMAIN_URL = "domain_url"; + private EditText mUrlEditText; private AppCompatButton mGoBtn; @@ -69,15 +71,10 @@ public class GotoActivity extends AppCompatActivity { urlString = "hifi://" + urlString; } - Intent intent = new Intent(this, InterfaceActivity.class); - intent.putExtra(InterfaceActivity.DOMAIN_URL, urlString); + Intent intent = new Intent(); + intent.putExtra(GotoActivity.PARAM_DOMAIN_URL, urlString); + setResult(RESULT_OK, intent); finish(); - if (getIntent() != null && - getIntent().hasExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY) && - getIntent().getBooleanExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { - intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - } - startActivity(intent); } } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java index ed442e2d8d..fd50d36c75 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java @@ -31,6 +31,9 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On * Set this intent extra param to NOT start a new InterfaceActivity after a domain is selected" */ public static final String PARAM_NOT_START_INTERFACE_ACTIVITY = "not_start_interface_activity"; + + public static final int ENTER_DOMAIN_URL = 1; + private DomainAdapter domainAdapter; private DrawerLayout mDrawerLayout; private ProgressDialog mDialog; @@ -89,15 +92,7 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On @Override public void onItemClick(View view, int position, DomainAdapter.Domain domain) { - Intent intent = new Intent(HomeActivity.this, InterfaceActivity.class); - intent.putExtra(InterfaceActivity.DOMAIN_URL, domain.url); - HomeActivity.this.finish(); - if (getIntent() != null && - getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) && - getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { - intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - } - startActivity(intent); + gotoDomain(domain.url); } }); domainsView.setAdapter(domainAdapter); @@ -121,6 +116,18 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On } + private void gotoDomain(String domainUrl) { + Intent intent = new Intent(HomeActivity.this, InterfaceActivity.class); + intent.putExtra(InterfaceActivity.DOMAIN_URL, domainUrl); + HomeActivity.this.finish(); + if (getIntent() != null && + getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) && + getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) { + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + } + startActivity(intent); + } + private void showActivityIndicator() { if (mDialog == null) { mDialog = new ProgressDialog(this); @@ -190,11 +197,20 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On switch(item.getItemId()) { case R.id.action_goto: Intent i = new Intent(this, GotoActivity.class); - startActivity(i); + startActivityForResult(i, ENTER_DOMAIN_URL); return true; case R.id.action_settings: return true; } return false; } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == ENTER_DOMAIN_URL && resultCode == RESULT_OK) { + gotoDomain(data.getStringExtra(GotoActivity.PARAM_DOMAIN_URL)); + } + } + } From 472cc1b29a2625452611372f80de9fb0451d7c55 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 18 Apr 2018 16:44:49 -0300 Subject: [PATCH 025/174] Fix code spacing --- android/app/src/main/assets/hifi_domains.json | 2 +- .../io/highfidelity/hifiinterface/GotoActivity.java | 2 +- .../io/highfidelity/hifiinterface/HomeActivity.java | 10 +++++----- .../highfidelity/hifiinterface/InterfaceActivity.java | 2 +- .../io/highfidelity/interface/InterfaceActivity.java | 1 - scripts/system/+android/actionbar.js | 2 +- scripts/system/+android/bottombar.js | 4 ++-- scripts/system/+android/modes.js | 2 +- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/android/app/src/main/assets/hifi_domains.json b/android/app/src/main/assets/hifi_domains.json index 216b24e639..a63ef7b6aa 100644 --- a/android/app/src/main/assets/hifi_domains.json +++ b/android/app/src/main/assets/hifi_domains.json @@ -1,7 +1,7 @@ { "hifi_domains" : [ { - "name": "You last location", + "name": "Your last location", "url": "", "thumbnail": "" }, diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java index a83f93d080..995e64c2a5 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/GotoActivity.java @@ -67,7 +67,7 @@ public class GotoActivity extends AppCompatActivity { } catch (URISyntaxException e) { return; } - if (uri.getScheme()==null || uri.getScheme().isEmpty()) { + if (uri.getScheme() == null || uri.getScheme().isEmpty()) { urlString = "hifi://" + urlString; } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java index fd50d36c75..63e0870d58 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java @@ -56,7 +56,7 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On mNavigationView = (NavigationView) findViewById(R.id.nav_view); mNavigationView.setNavigationItemSelectedListener(this); - TabHost tabs=(TabHost)findViewById(R.id.tabhost); + TabHost tabs = (TabHost)findViewById(R.id.tabhost); tabs.setup(); TabHost.TabSpec spec=tabs.newTabSpec("featured"); @@ -64,12 +64,12 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On spec.setIndicator(getString(R.string.featured)); tabs.addTab(spec); - spec=tabs.newTabSpec("popular"); + spec = tabs.newTabSpec("popular"); spec.setContent(R.id.popular); spec.setIndicator(getString(R.string.popular)); tabs.addTab(spec); - spec=tabs.newTabSpec("bookmarks"); + spec = tabs.newTabSpec("bookmarks"); spec.setContent(R.id.bookmarks); spec.setIndicator(getString(R.string.bookmarks)); tabs.addTab(spec); @@ -77,7 +77,7 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On tabs.setCurrentTab(0); TabWidget tabwidget=tabs.getTabWidget(); - for(int i=0;i Date: Thu, 19 Apr 2018 11:41:59 -0300 Subject: [PATCH 026/174] Remove debug statements and unused code. Put JNI code in a separated file. --- .../hifiinterface/InterfaceActivity.java | 2 +- .../resources/qml/hifi/+android/modesbar.qml | 2 +- interface/src/Application.cpp | 48 ++----------------- interface/src/Application.h | 2 - interface/src/Application_jni.cpp | 18 +++++++ scripts/system/+android/actionbar.js | 2 +- scripts/system/+android/goto.js | 2 +- 7 files changed, 25 insertions(+), 51 deletions(-) create mode 100644 interface/src/Application_jni.cpp diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index 52da11f1a9..32b6e0e039 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -199,7 +199,7 @@ public class InterfaceActivity extends QtActivity { public void openGotoActivity(String activityName) { switch (activityName) { - case "Goto": { + case "Home": { Intent intent = new Intent(this, HomeActivity.class); intent.putExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, true); startActivity(intent); diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml index 98973f1edb..994bf1efe4 100644 --- a/interface/resources/qml/hifi/+android/modesbar.qml +++ b/interface/resources/qml/hifi/+android/modesbar.qml @@ -15,7 +15,7 @@ Item { function relocateAndResize(newWindowWidth, newWindowHeight) { width = 300; height = 300; - x=newWindowWidth - 565; + x = newWindowWidth - 565; } function onWindowGeometryChanged(rect) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9fee772513..19267a59ee 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7862,71 +7862,29 @@ void Application::saveNextPhysicsStats(QString filename) { void Application::openAndroidActivity(const QString& activityName) { #if defined(Q_OS_ANDROID) - qDebug() << "[Background-HIFI] Application::openAndroidActivity"; - //getActiveDisplayPlugin()->deactivate(); AndroidHelper::instance().requestActivity(activityName); - connect(&AndroidHelper::instance(), &AndroidHelper::backFromAndroidActivity, this, &Application::restoreAfterAndroidActivity); -#endif -} - -void Application::restoreAfterAndroidActivity() { -#if defined(Q_OS_ANDROID) - qDebug() << "[Background-HIFI] restoreAfterAndroidActivity: this wouldn't be needed"; - - /*if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { - qWarning() << "Could not re-activate display plugin"; - }*/ - disconnect(&AndroidHelper::instance(), &AndroidHelper::backFromAndroidActivity, this, &Application::restoreAfterAndroidActivity); #endif } #if defined(Q_OS_ANDROID) void Application::enterBackground() { - qDebug() << "[Background-HIFI] enterBackground begin"; QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::BlockingQueuedConnection); - qDebug() << "[Background-HIFI] deactivating display plugin"; getActiveDisplayPlugin()->deactivate(); - qDebug() << "[Background-HIFI] enterBackground end"; } void Application::enterForeground() { - qDebug() << "[Background-HIFI] enterForeground qApp?" << (qApp?"yeah":"false"); if (qApp && DependencyManager::isSet()) { - qDebug() << "[Background-HIFI] audioclient.start()"; QMetaObject::invokeMethod(DependencyManager::get().data(), "start", Qt::BlockingQueuedConnection); } else { - qDebug() << "[Background-HIFI] audioclient.start() not done"; + qDebug() << "Could not start AudioClient"; } if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { - qWarning() << "[Background-HIFI] Could not re-activate display plugin"; + qWarning() << "Could not re-activate display plugin"; } } - -extern "C" { - - -JNIEXPORT void -Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterBackground(JNIEnv *env, jobject obj) { - qDebug() << "[Background-HIFI] nativeEnterBackground"; - if (qApp) { - qDebug() << "[Background-HIFI] nativeEnterBackground begin (qApp)"; - qApp->enterBackground(); - } -} - -JNIEXPORT void -Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterForeground(JNIEnv *env, jobject obj) { - qDebug() << "[Background-HIFI] nativeEnterForeground"; - if (qApp) { - qDebug() << "[Background-HIFI] nativeEnterForeground begin (qApp)"; - qApp->enterForeground(); - } -} - - -} +#include "Application_jni.cpp" #endif diff --git a/interface/src/Application.h b/interface/src/Application.h index ec49aa055f..568cce2ab6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -459,8 +459,6 @@ private slots: void handleSandboxStatus(QNetworkReply* reply); void switchDisplayMode(); - void restoreAfterAndroidActivity(); - private: static void initDisplay(); void init(); diff --git a/interface/src/Application_jni.cpp b/interface/src/Application_jni.cpp new file mode 100644 index 0000000000..83641ad8c6 --- /dev/null +++ b/interface/src/Application_jni.cpp @@ -0,0 +1,18 @@ +extern "C" { + +JNIEXPORT void +Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterBackground(JNIEnv *env, jobject obj) { + if (qApp) { + qApp->enterBackground(); + } +} + +JNIEXPORT void +Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterForeground(JNIEnv *env, jobject obj) { + if (qApp) { + qApp->enterForeground(); + } +} + + +} diff --git a/scripts/system/+android/actionbar.js b/scripts/system/+android/actionbar.js index a1ddc6f2de..1f0872d5ee 100644 --- a/scripts/system/+android/actionbar.js +++ b/scripts/system/+android/actionbar.js @@ -38,7 +38,7 @@ function init() { } function onBackPressed() { - App.openAndroidActivity("Goto"); + App.openAndroidActivity("Home"); } diff --git a/scripts/system/+android/goto.js b/scripts/system/+android/goto.js index 540705c673..750844a2a4 100644 --- a/scripts/system/+android/goto.js +++ b/scripts/system/+android/goto.js @@ -34,7 +34,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See module.exports.onHidden(); break; case 'openAndroidActivity': - App.openAndroidActivity("Goto"); + App.openAndroidActivity("Home"); break; default: print('[goto-android.js] Unrecognized message from AddressBarDialog.qml:', JSON.stringify(message)); From a0b5d9a78d5fb9c9af3c83fa4453f2c00cd122c2 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 19 Apr 2018 14:33:38 -0300 Subject: [PATCH 027/174] Rename openGotoActivity to openAndroidActivity --- android/app/src/main/cpp/native.cpp | 2 +- .../java/io/highfidelity/hifiinterface/InterfaceActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index c71be76b3e..facf6bd4bd 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -151,7 +151,7 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCrea QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [](const QString& a) { QAndroidJniObject string = QAndroidJniObject::fromString(a); - __activity.callMethod("openGotoActivity", "(Ljava/lang/String;)V", string.object()); + __activity.callMethod("openAndroidActivity", "(Ljava/lang/String;)V", string.object()); }); } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index 32b6e0e039..dd758704e0 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -197,7 +197,7 @@ public class InterfaceActivity extends QtActivity { nativeGoBackFromAndroidActivity(); } - public void openGotoActivity(String activityName) { + public void openAndroidActivity(String activityName) { switch (activityName) { case "Home": { Intent intent = new Intent(this, HomeActivity.class); From f2184bf4568f7c388a1883954a58e38e1ca15792 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 19 Apr 2018 17:31:25 -0300 Subject: [PATCH 028/174] Handle android back button. Remove unused resources. Fix compilation errors. --- .../hifiinterface/HomeActivity.java | 4 + .../hifiinterface/InterfaceActivity.java | 4 + .../resources/icons/+android/avatar-a.svg | 38 - .../resources/icons/+android/avatar-i.svg | 38 - interface/resources/icons/+android/goto-a.svg | 28 - interface/resources/icons/+android/goto-i.svg | 28 - interface/resources/icons/+android/home.svg | 82 -- .../resources/icons/+android/login-a.svg | 990 ------------------ .../resources/icons/+android/login-i.svg | 990 ------------------ .../qml/+android/AddressBarDialog.qml | 232 ---- .../resources/qml/+android/LoginDialog.qml | 95 -- .../qml/hifi/+android/avatarSelection.qml | 179 ---- .../resources/qml/hifi/+android/bottombar.qml | 151 --- interface/src/Application.cpp | 17 +- interface/src/Application.h | 4 - interface/src/Application_jni.cpp | 6 + scripts/system/+android/avatarSelection.js | 164 --- scripts/system/+android/bottombar.js | 271 ----- scripts/system/+android/goto.js | 108 -- 19 files changed, 23 insertions(+), 3406 deletions(-) delete mode 100755 interface/resources/icons/+android/avatar-a.svg delete mode 100755 interface/resources/icons/+android/avatar-i.svg delete mode 100755 interface/resources/icons/+android/goto-a.svg delete mode 100644 interface/resources/icons/+android/goto-i.svg delete mode 100644 interface/resources/icons/+android/home.svg delete mode 100755 interface/resources/icons/+android/login-a.svg delete mode 100755 interface/resources/icons/+android/login-i.svg delete mode 100644 interface/resources/qml/+android/AddressBarDialog.qml delete mode 100644 interface/resources/qml/+android/LoginDialog.qml delete mode 100644 interface/resources/qml/hifi/+android/avatarSelection.qml delete mode 100644 interface/resources/qml/hifi/+android/bottombar.qml delete mode 100644 scripts/system/+android/avatarSelection.js delete mode 100644 scripts/system/+android/bottombar.js delete mode 100644 scripts/system/+android/goto.js diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java index 63e0870d58..611c8f50cc 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HomeActivity.java @@ -213,4 +213,8 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On } } + @Override + public void onBackPressed() { + finishAffinity(); + } } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index dd758704e0..d2aff85323 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -212,4 +212,8 @@ public class InterfaceActivity extends QtActivity { } } + @Override + public void onBackPressed() { + openAndroidActivity("Home"); + } } \ No newline at end of file diff --git a/interface/resources/icons/+android/avatar-a.svg b/interface/resources/icons/+android/avatar-a.svg deleted file mode 100755 index 165b39943e..0000000000 --- a/interface/resources/icons/+android/avatar-a.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - diff --git a/interface/resources/icons/+android/avatar-i.svg b/interface/resources/icons/+android/avatar-i.svg deleted file mode 100755 index c1557487ea..0000000000 --- a/interface/resources/icons/+android/avatar-i.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - diff --git a/interface/resources/icons/+android/goto-a.svg b/interface/resources/icons/+android/goto-a.svg deleted file mode 100755 index 5fb3e52e4c..0000000000 --- a/interface/resources/icons/+android/goto-a.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - diff --git a/interface/resources/icons/+android/goto-i.svg b/interface/resources/icons/+android/goto-i.svg deleted file mode 100644 index 7613beb9e7..0000000000 --- a/interface/resources/icons/+android/goto-i.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - diff --git a/interface/resources/icons/+android/home.svg b/interface/resources/icons/+android/home.svg deleted file mode 100644 index 414c179e79..0000000000 --- a/interface/resources/icons/+android/home.svg +++ /dev/null @@ -1,82 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/interface/resources/icons/+android/login-a.svg b/interface/resources/icons/+android/login-a.svg deleted file mode 100755 index 8a7f097ed7..0000000000 --- a/interface/resources/icons/+android/login-a.svg +++ /dev/null @@ -1,990 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/interface/resources/icons/+android/login-i.svg b/interface/resources/icons/+android/login-i.svg deleted file mode 100755 index 6f011e1d13..0000000000 --- a/interface/resources/icons/+android/login-i.svg +++ /dev/null @@ -1,990 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/interface/resources/qml/+android/AddressBarDialog.qml b/interface/resources/qml/+android/AddressBarDialog.qml deleted file mode 100644 index e3fcad2b5e..0000000000 --- a/interface/resources/qml/+android/AddressBarDialog.qml +++ /dev/null @@ -1,232 +0,0 @@ -// -// AddressBarDialog.qml -// -// Created by Austin Davis on 2015/04/14 -// Copyright 2015 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 -// - -import Hifi 1.0 -import QtQuick 2.4 -import "../controls" -import "../styles" -import "../hifi" as QmlHifi -import "../hifi/toolbars" -import "../styles-uit" as HifiStyles -import "../controls-uit" as HifiControls - -Item { - QmlHifi.HifiConstants { id: android } - - width: parent ? parent.width - android.dimen.windowLessWidth : 0 - height: parent ? parent.height - android.dimen.windowLessHeight : 0 - z: android.dimen.windowZ - anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom } - - id: bar - property bool isCursorVisible: false // Override default cursor visibility. - property bool shown: true - - onShownChanged: { - bar.visible = shown; - sendToScript({method: 'shownChanged', params: { shown: shown }}); - if (shown) { - addressLine.text=""; - updateLocationText(addressLine.text.length > 0); - } - } - - function hide() { - shown = false; - sendToScript ({ type: "hide" }); - } - - Component.onCompleted: { - updateLocationText(addressLine.text.length > 0); - } - - HifiConstants { id: hifi } - HifiStyles.HifiConstants { id: hifiStyleConstants } - - signal sendToScript(var message); - - AddressBarDialog { - id: addressBarDialog - } - - - Rectangle { - id: background - gradient: Gradient { - GradientStop { position: 0.0; color: android.color.gradientTop } - GradientStop { position: 1.0; color: android.color.gradientBottom } - } - anchors { - fill: parent - } - - MouseArea { - anchors.fill: parent - } - - QmlHifi.WindowHeader { - id: header - iconSource: "../../../icons/goto-i.svg" - titleText: "GO TO" - } - - HifiStyles.RalewayRegular { - id: notice - text: "YOUR LOCATION" - font.pixelSize: (hifi.fonts.pixelSize * 2.15) * (android.dimen.atLeast1440p ? 1 : .75); - color: "#2CD7FF" - anchors { - bottom: addressBackground.top - bottomMargin: android.dimen.atLeast1440p ? 45 : 34 - left: addressBackground.left - leftMargin: android.dimen.atLeast1440p ? 60 : 45 - } - - } - - property int inputAreaHeight: android.dimen.atLeast1440p ? 210 : 156 - property int inputAreaStep: (height - inputAreaHeight) / 2 - - ToolbarButton { - id: homeButton - y: android.dimen.atLeast1440p ? 280 : 210 - imageURL: "../../icons/home.svg" - onClicked: { - sendToScript({method: 'openAndroidActivity', params: {}}); - hide(); - } - anchors { - leftMargin: android.dimen.atLeast1440p ? 75 : 56 - left: parent.left - } - size: android.dimen.atLeast1440p ? 150 : 150//112 - } - - ToolbarButton { - id: backArrow; - imageURL: "../../icons/backward.svg"; - onClicked: addressBarDialog.loadBack(); - anchors { - left: homeButton.right - leftMargin: android.dimen.atLeast1440p ? 70 : 52 - verticalCenter: homeButton.verticalCenter - } - size: android.dimen.atLeast1440p ? 150 : 150 - } - ToolbarButton { - id: forwardArrow; - imageURL: "../../icons/forward.svg"; - onClicked: addressBarDialog.loadForward(); - anchors { - left: backArrow.right - leftMargin: android.dimen.atLeast1440p ? 60 : 45 - verticalCenter: homeButton.verticalCenter - } - size: android.dimen.atLeast1440p ? 150 : 150 - } - - HifiStyles.FiraSansRegular { - id: location; - font.pixelSize: addressLine.font.pixelSize; - color: "lightgray"; - clip: true; - anchors.fill: addressLine; - visible: addressLine.text.length === 0 - z: 1 - } - - Rectangle { - id: addressBackground - x: android.dimen.atLeast1440p ? 780 : 585 - y: android.dimen.atLeast1440p ? 280 : 235 // tweaking by hand - width: android.dimen.atLeast1440p ? 1270 : 952 - height: android.dimen.atLeast1440p ? 150 : 112 - color: "#FFFFFF" - } - - TextInput { - id: addressLine - focus: true - x: android.dimen.atLeast1440p ? 870 : 652 - y: android.dimen.atLeast1440p ? 300 : 245 // tweaking by hand - width: android.dimen.atLeast1440p ? 1200 : 900 - height: android.dimen.atLeast1440p ? 120 : 90 - inputMethodHints: Qt.ImhNoPredictiveText - //helperText: "Hint is here" - font.pixelSize: hifi.fonts.pixelSize * 3.75 - onTextChanged: { - //filterChoicesByText(); - updateLocationText(addressLine.text.length > 0); - if (!isCursorVisible && text.length > 0) { - isCursorVisible = true; - cursorVisible = true; - } - } - - onActiveFocusChanged: { - //cursorVisible = isCursorVisible && focus; - } - } - - - - function toggleOrGo() { - if (addressLine.text !== "") { - addressBarDialog.loadAddress(addressLine.text); - } - bar.shown = false; - } - - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Escape: - case Qt.Key_Back: - clearAddressLineTimer.start(); - event.accepted = true - bar.shown = false; - break - case Qt.Key_Enter: - case Qt.Key_Return: - toggleOrGo(); - clearAddressLineTimer.start(); - event.accepted = true - break - } - } - - } - - Timer { - // Delay clearing address line so as to avoid flicker of "not connected" being displayed after entering an address. - id: clearAddressLineTimer - running: false - interval: 100 // ms - repeat: false - onTriggered: { - addressLine.text = ""; - isCursorVisible = false; - } - } - - function updateLocationText(enteringAddress) { - if (enteringAddress) { - notice.text = "Go to a place, @user, path or network address"; - notice.color = "#ffffff"; // hifiStyleConstants.colors.baseGrayHighlight; - location.visible = false; - } else { - notice.text = AddressManager.isConnected ? "YOUR LOCATION:" : "NOT CONNECTED"; - notice.color = AddressManager.isConnected ? hifiStyleConstants.colors.blueHighlight : hifiStyleConstants.colors.redHighlight; - // Display hostname, which includes ip address, localhost, and other non-placenames. - location.text = (AddressManager.placename || AddressManager.hostname || '') + (AddressManager.pathname ? AddressManager.pathname.match(/\/[^\/]+/)[0] : ''); - location.visible = true; - } - } - -} diff --git a/interface/resources/qml/+android/LoginDialog.qml b/interface/resources/qml/+android/LoginDialog.qml deleted file mode 100644 index 567cca9bcf..0000000000 --- a/interface/resources/qml/+android/LoginDialog.qml +++ /dev/null @@ -1,95 +0,0 @@ -// -// LoginDialog.qml -// -// Created by David Rowe on 3 Jun 2015 -// Copyright 2015 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 -// - -import Hifi 1.0 -import QtQuick 2.4 - -import "controls-uit" -import "styles-uit" -import "windows" - -import "LoginDialog" - -ModalWindow { - id: root - HifiConstants { id: hifi } - - objectName: "LoginDialog" - implicitWidth: 1560 - implicitHeight: 450 - y:0 - destroyOnCloseButton: true - destroyOnHidden: true - visible: true - - property string iconText: "" - property int iconSize: 105 - - property string title: "" - property int titleWidth: 0 - - keyboardOverride: true // Disable ModalWindow's keyboard. - - function tryDestroy() { - Controller.setVPadHidden(false); - root.destroy(); - } - - LoginDialog { - id: loginDialog - - Loader { - id: bodyLoader - source: loginDialog.isSteamRunning() ? "LoginDialog/+android/SignInBody.qml" : "LoginDialog/+android/LinkAccountBody.qml" - } - } - - Component.onCompleted: { - this.anchors.centerIn = undefined; - this.y = 150; - this.x = (parent.width - this.width) / 2; - Controller.setVPadHidden(true); - } - - Keys.onPressed: { - if (!visible) { - return - } - - if (event.modifiers === Qt.ControlModifier) - switch (event.key) { - case Qt.Key_A: - event.accepted = true - detailedText.selectAll() - break - case Qt.Key_C: - event.accepted = true - detailedText.copy() - break - case Qt.Key_Period: - if (Qt.platform.os === "osx") { - event.accepted = true - content.reject() - } - break - } else switch (event.key) { - case Qt.Key_Escape: - case Qt.Key_Back: - event.accepted = true - destroy() - break - - case Qt.Key_Enter: - case Qt.Key_Return: - event.accepted = true - break - } - } -} diff --git a/interface/resources/qml/hifi/+android/avatarSelection.qml b/interface/resources/qml/hifi/+android/avatarSelection.qml deleted file mode 100644 index afa5634575..0000000000 --- a/interface/resources/qml/hifi/+android/avatarSelection.qml +++ /dev/null @@ -1,179 +0,0 @@ -// -// avatarSelection.qml -// interface/resources/qml/android -// -// Created by Gabriel Calero & Cristian Duarte on 21 Sep 2017 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.5 -import QtQuick.Layouts 1.3 -import Hifi 1.0 - -import "../../styles" -import "." -import ".." -import ".." as QmlHifi -import "../../styles-uit" as HifiStyles - - -Item { - - id: top - - HifiConstants { id: android } - width: parent ? parent.width - android.dimen.windowLessWidth : 0 - height: parent ? parent.height - android.dimen.windowLessHeight : 0 - z: android.dimen.windowZ - anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom } - - signal sendToScript(var message); - - property bool shown: true - - onShownChanged: { - top.visible = shown; - } - - - HifiConstants { id: hifi } - HifiStyles.HifiConstants { id: hifiStyleConstants } - - property int cardWidth: 250 *3; - property int cardHeight: 240 *3; - property int gap: 14 *3; - - property var avatarsArray: []; - property var extraOptionsArray: []; - - function hide() { - shown = false; - sendToScript ({ method: "hide" }); - } - - Rectangle { - - width: parent ? parent.width : 0 - height: parent ? parent.height : 0 - - MouseArea { - anchors.fill: parent - } - - gradient: Gradient { - GradientStop { position: 0.0; color: android.color.gradientTop } - GradientStop { position: 1.0; color: android.color.gradientBottom } - } - - QmlHifi.WindowHeader { - id: header - iconSource: "../../../../icons/avatar-i.svg" - titleText: "AVATAR" - } - - ListModel { id: avatars } - - ListView { - id: scroll - height: 250*3 - property int stackedCardShadowHeight: 10*3; - spacing: gap; - clip: true; - anchors { - left: parent.left - right: parent.right - top: header.bottom - topMargin: gap - leftMargin: gap - rightMargin: gap - } - model: avatars; - orientation: ListView.Horizontal; - delegate: QmlHifi.AvatarOption { - type: model.type; - thumbnailUrl: model.thumbnailUrl; - avatarUrl: model.avatarUrl; - avatarName: model.avatarName; - avatarSelected: model.avatarSelected; - methodName: model.methodName; - actionText: model.actionText; - } - highlightMoveDuration: -1; - highlightMoveVelocity: -1; - } - - } - - function escapeRegExp(str) { - return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); - } - function replaceAll(str, find, replace) { - return str.replace(new RegExp(escapeRegExp(find), 'g'), replace); - } - - function refreshSelected(selectedAvatarUrl) { - // URL as ID? - avatarsArray.forEach(function (avatarData) { - avatarData.avatarSelected = (selectedAvatarUrl == avatarData.avatarUrl); - console.log('[avatarSelection] avatar : ', avatarData.avatarName, ' is selected? ' , avatarData.avatarSelected); - }); - } - - function addAvatar(name, thumbnailUrl, avatarUrl) { - avatarsArray.push({ - type: "avatar", - thumbnailUrl: thumbnailUrl, - avatarUrl: avatarUrl, - avatarName: name, - avatarSelected: false, - methodName: "", - actionText: "" - }); - } - - function showAvatars() { - avatars.clear(); - avatarsArray.forEach(function (avatarData) { - avatars.append(avatarData); - console.log('[avatarSelection] adding avatar to model: ', JSON.stringify(avatarData)); - }); - extraOptionsArray.forEach(function (extraData) { - avatars.append(extraData); - console.log('[avatarSelection] adding extra option to model: ', JSON.stringify(extraData)); - }); - } - - function addExtraOption(showName, thumbnailUrl, methodNameWhenClicked, actionText) { - extraOptionsArray.push({ - type: "extra", - thumbnailUrl: thumbnailUrl, - avatarUrl: "", - avatarName: showName, - avatarSelected: false, - methodName: methodNameWhenClicked, - actionText: actionText - }); - } - - function fromScript(message) { - //console.log("[CHAT] fromScript " + JSON.stringify(message)); - switch (message.type) { - case "addAvatar": - addAvatar(message.name, message.thumbnailUrl, message.avatarUrl); - break; - case "addExtraOption": - //(showName, thumbnailUrl, methodNameWhenClicked, actionText) - addExtraOption(message.showName, message.thumbnailUrl, message.methodNameWhenClicked, message.actionText); - break; - case "refreshSelected": - refreshSelected(message.selectedAvatarUrl); - break; - case "showAvatars": - showAvatars(); - break; - default: - } - } -} \ No newline at end of file diff --git a/interface/resources/qml/hifi/+android/bottombar.qml b/interface/resources/qml/hifi/+android/bottombar.qml deleted file mode 100644 index 66117d0389..0000000000 --- a/interface/resources/qml/hifi/+android/bottombar.qml +++ /dev/null @@ -1,151 +0,0 @@ -// -// bottomHudOptions.qml -// interface/resources/qml/android -// -// Created by Gabriel Calero & Cristian Duarte on 19 Jan 2018 -// 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 -// - -import Hifi 1.0 -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 -import QtQuick.Layouts 1.3 -import Qt.labs.settings 1.0 -import "../../styles" as Styles -import "../../styles-uit" -import "../../controls-uit" as HifiControlsUit -import "../../controls" as HifiControls -import ".." -import "." - -Item { - id: bar - x:0 - height: 255 - - property bool shown: true - - signal sendToScript(var message); - - onShownChanged: { - bar.visible = shown; - } - - function hide() { - //shown = false; - sendToScript({ method: "hide" }); - } - - Styles.HifiConstants { id: hifi } - HifiConstants { id: android } - MouseArea { - anchors.fill: parent - } - - Rectangle { - id: background - anchors.fill : parent - color: "#FF000000" - border.color: "#FFFFFF" - anchors.bottomMargin: -1 - anchors.leftMargin: -1 - anchors.rightMargin: -1 - Flow { - id: flowMain - spacing: 10 - anchors.fill: parent - anchors.topMargin: 12 - anchors.bottomMargin: 12 - anchors.rightMargin: 12 - anchors.leftMargin: 72 - } - - - Rectangle { - id: hideButton - height: android.dimen.headerHideWidth - width: android.dimen.headerHideHeight - color: "#00000000" - anchors { - right: parent.right - rightMargin: android.dimen.headerHideRightMargin - top: parent.top - topMargin: android.dimen.headerHideTopMargin - } - - Image { - id: hideIcon - source: "../../../icons/hide.svg" - width: android.dimen.headerHideIconWidth - height: android.dimen.headerHideIconHeight - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.top - } - } - FiraSansRegular { - anchors { - top: hideIcon.bottom - horizontalCenter: hideIcon.horizontalCenter - topMargin: 12 - } - text: "HIDE" - color: "#FFFFFF" - font.pixelSize: hifi.fonts.pixelSize * 2.5; - } - - MouseArea { - anchors.fill: parent - onClicked: { - hide(); - } - } - } - } - - function relocateAndResize(newWindowWidth, newWindowHeight) { - width = newWindowWidth; - y = newWindowHeight - height; - } - - function onWindowGeometryChanged(rect) { - relocateAndResize(rect.width, rect.height); - } - - Component.onCompleted: { - // put on bottom - relocateAndResize(Window.innerWidth, Window.innerHeight); - Window.geometryChanged.connect(onWindowGeometryChanged); // In devices with bars appearing at startup we should listen for this - } - - Component.onDestruction: { - Window.geometryChanged.disconnect(onWindowGeometryChanged); - } - - function addButton(properties) { - var component = Qt.createComponent("button.qml"); - if (component.status == Component.Ready) { - var button = component.createObject(flowMain); - // copy all properites to button - var keys = Object.keys(properties).forEach(function (key) { - button[key] = properties[key]; - }); - return button; - } else if( component.status == Component.Error) { - console.log("Load button errors " + component.errorString()); - } - } - - function urlHelper(src) { - if (src.match(/\bhttp/)) { - return src; - } else { - return "../../../" + src; - } - } - -} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 19267a59ee..b478dd1807 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -242,7 +242,7 @@ extern "C" { #if defined(Q_OS_ANDROID) #include -#include +#include "AndroidHelper.h" #endif enum ApplicationEvent { @@ -3623,6 +3623,12 @@ void Application::keyPressEvent(QKeyEvent* event) { void Application::keyReleaseEvent(QKeyEvent* event) { _keysPressed.remove(event->key()); +#if defined(Q_OS_ANDROID) + if (event->key() == Qt::Key_Back) { + event->accept(); + openAndroidActivity("Home"); + } +#endif _controllerScriptingInterface->emitKeyReleaseEvent(event); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it @@ -7873,19 +7879,14 @@ void Application::enterBackground() { getActiveDisplayPlugin()->deactivate(); } void Application::enterForeground() { - if (qApp && DependencyManager::isSet()) { - QMetaObject::invokeMethod(DependencyManager::get().data(), + QMetaObject::invokeMethod(DependencyManager::get().data(), "start", Qt::BlockingQueuedConnection); - } else { - qDebug() << "Could not start AudioClient"; - } if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { qWarning() << "Could not re-activate display plugin"; } } -#include "Application_jni.cpp" - #endif +#include "Application_jni.cpp" #include "Application.moc" diff --git a/interface/src/Application.h b/interface/src/Application.h index 568cce2ab6..7af8a679bf 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -78,10 +78,6 @@ #include "Sound.h" -#if defined(Q_OS_ANDROID) -#include "AndroidHelper.h" -#endif - class OffscreenGLCanvas; class GLCanvas; class FaceTracker; diff --git a/interface/src/Application_jni.cpp b/interface/src/Application_jni.cpp index 83641ad8c6..5e9f1ac29e 100644 --- a/interface/src/Application_jni.cpp +++ b/interface/src/Application_jni.cpp @@ -1,3 +1,8 @@ +#if defined(Q_OS_ANDROID) + +#include +#include "AndroidHelper.h" + extern "C" { JNIEXPORT void @@ -16,3 +21,4 @@ Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterForeground(JNIEn } +#endif \ No newline at end of file diff --git a/scripts/system/+android/avatarSelection.js b/scripts/system/+android/avatarSelection.js deleted file mode 100644 index 2946e541b5..0000000000 --- a/scripts/system/+android/avatarSelection.js +++ /dev/null @@ -1,164 +0,0 @@ -"use strict"; -// -// avatarSelection.js -// scripts/system/ -// -// Created by Gabriel Calero & Cristian Duarte on 21 Sep 2017 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var window; - -var logEnabled = true; -var isVisible = false; - -function printd(str) { - if (logEnabled) - print("[avatarSelection.js] " + str); -} - -function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var data; - printd("fromQml " + JSON.stringify(message)); - switch (message.method) { - case 'selectAvatar': - // use this message.params.avatarUrl - printd("Selected Avatar: [" + message.params.avatarUrl + "]"); - App.askBeforeSetAvatarUrl(message.params.avatarUrl); - break; - case 'openAvatarMarket': - // good - App.openUrl("https://metaverse.highfidelity.com/marketplace?category=avatars"); - break; - case 'hide': - Controller.setVPadHidden(false); - module.exports.hide(); - module.exports.onHidden(); - break; - default: - print('[avatarSelection.js] Unrecognized message from avatarSelection.qml:', JSON.stringify(message)); - } -} - -function sendToQml(message) { - if (!window) { - print("[avatarSelection.js] There is no window object"); - return; - } - window.sendToQml(message); -} - -function refreshSelected(currentAvatarURL) { - sendToQml({ - type: "refreshSelected", - selectedAvatarUrl: currentAvatarURL - }); - - sendToQml({ - type: "showAvatars" - }); -} - -function init() { - if (!window) { - print("[avatarSelection.js] There is no window object for init()"); - return; - } - var DEFAULT_AVATAR_URL = "http://mpassets.highfidelity.com/7fe80a1e-f445-4800-9e89-40e677b03bee-v3/mannequin.fst"; - sendToQml({ - type: "addAvatar", - name: "Wooden Mannequin", - thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/7fe80a1e-f445-4800-9e89-40e677b03bee/thumbnail/hifi-mp-7fe80a1e-f445-4800-9e89-40e677b03bee.jpg", - avatarUrl: DEFAULT_AVATAR_URL - }); - sendToQml({ - type: "addAvatar", - name: "Cody", - thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/8c859fca-4cbd-4e82-aad1-5f4cb0ca5d53/thumbnail/hifi-mp-8c859fca-4cbd-4e82-aad1-5f4cb0ca5d53.jpg", - avatarUrl: "http://mpassets.highfidelity.com/8c859fca-4cbd-4e82-aad1-5f4cb0ca5d53-v1/cody.fst" - }); - sendToQml({ - type: "addAvatar", - name: "Mixamo Will", - thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73/thumbnail/hifi-mp-d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73.jpg", - avatarUrl: "http://mpassets.highfidelity.com/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73-v1/4618d52e711fbb34df442b414da767bb.fst" - }); - sendToQml({ - type: "addAvatar", - name: "Albert", - thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/1e57c395-612e-4acd-9561-e79dbda0bc49/thumbnail/hifi-mp-1e57c395-612e-4acd-9561-e79dbda0bc49.jpg", - avatarUrl: "http://mpassets.highfidelity.com/1e57c395-612e-4acd-9561-e79dbda0bc49-v1/albert.fst" - }); - /* We need to implement the wallet, so let's skip this for the moment - sendToQml({ - type: "addExtraOption", - showName: "More choices", - thumbnailUrl: "../../../images/moreAvatars.png", - methodNameWhenClicked: "openAvatarMarket", - actionText: "MARKETPLACE" - }); - */ - var currentAvatarURL = Settings.getValue('Avatar/fullAvatarURL', DEFAULT_AVATAR_URL); - printd("Default Avatar: [" + DEFAULT_AVATAR_URL + "]"); - printd("Current Avatar: [" + currentAvatarURL + "]"); - if (!currentAvatarURL || 0 === currentAvatarURL.length) { - currentAvatarURL = DEFAULT_AVATAR_URL; - } - refreshSelected(currentAvatarURL); -} - -module.exports = { - init: function() { - window = new QmlFragment({ - qml: "hifi/avatarSelection.qml", - visible: false - }); - if (window) { - window.fromQml.connect(fromQml); - } - init(); - }, - show: function() { - Controller.setVPadHidden(true); - if (window) { - window.setVisible(true); - isVisible = true; - } - }, - hide: function() { - Controller.setVPadHidden(false); - if (window) { - window.setVisible(false); - } - isVisible = false; - }, - destroy: function() { - Controller.setVPadHidden(false); - if (window) { - window.fromQml.disconnect(fromQml); - window.close(); - window = null; - } - }, - isVisible: function() { - return isVisible; - }, - width: function() { - return window ? window.size.x : 0; - }, - height: function() { - return window ? window.size.y : 0; - }, - position: function() { - return window && isVisible ? window.position : null; - }, - refreshSelectedAvatar: function(currentAvatarURL) { - refreshSelected(currentAvatarURL); - }, - onHidden: function() { - Controller.setVPadHidden(false); - } -}; diff --git a/scripts/system/+android/bottombar.js b/scripts/system/+android/bottombar.js deleted file mode 100644 index 526cd128e5..0000000000 --- a/scripts/system/+android/bottombar.js +++ /dev/null @@ -1,271 +0,0 @@ -"use strict"; -// -// bottombar.js -// scripts/system/ -// -// Created by Gabriel Calero & Cristian Duarte on Jan 18, 2018 -// 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 -// -(function() { // BEGIN LOCAL_SCOPE - -var bottombar; -var bottomHudOptionsBar; -var gotoBtn; -var avatarBtn; -var bubbleBtn; -var loginBtn; - -var gotoScript = Script.require('./goto.js'); -var avatarSelection = Script.require('./avatarSelection.js'); - -var logEnabled = false; - -function printd(str) { - if (logEnabled) { - print("[bottombar.js] " + str); - } -} - -function init() { - gotoScript.init(); - gotoScript.setOnShownChange(function (shown) { - if (shown) { - showAddressBar(); - } else { - hideAddressBar(); - } - }); - avatarSelection.init(); - App.fullAvatarURLChanged.connect(processedNewAvatar); - - setupBottomBar(); - setupBottomHudOptionsBar(); - - raiseBottomBar(); - - GlobalServices.connected.connect(handleLogin); - GlobalServices.myUsernameChanged.connect(onUsernameChanged); - GlobalServices.disconnected.connect(handleLogout); -} - -function shutdown() { - App.fullAvatarURLChanged.disconnect(processedNewAvatar); -} - -function setupBottomBar() { - bottombar = new QmlFragment({ - qml: "hifi/bottombar.qml" - }); - - bottombar.fromQml.connect(function(message) { - switch (message.method) { - case 'hide': - lowerBottomBar(); - break; - default: - print('[bottombar.js] Unrecognized message from bottomHud.qml:', JSON.stringify(message)); - } - }); - - avatarBtn = bottombar.addButton({ - icon: "icons/avatar-i.svg", - activeIcon: "icons/avatar-a.svg", - bgOpacity: 0, - height: 240, - width: 294, - hoverBgOpacity: 0, - activeBgOpacity: 0, - activeHoverBgOpacity: 0, - iconSize: 108, - textSize: 45, - text: "AVATAR" - }); - avatarBtn.clicked.connect(function() { - printd("Avatar button clicked"); - if (!avatarSelection.isVisible()) { - showAvatarSelection(); - } else { - hideAvatarSelection(); - } - }); - avatarSelection.onHidden = function() { - if (avatarBtn) { - avatarBtn.isActive = false; - } - }; - - gotoBtn = bottombar.addButton({ - icon: "icons/goto-i.svg", - activeIcon: "icons/goto-a.svg", - bgOpacity: 0, - hoverBgOpacity: 0, - activeBgOpacity: 0, - activeHoverBgOpacity: 0, - height: 240, - width: 294, - iconSize: 108, - textSize: 45, - text: "GO TO" - }); - - gotoBtn.clicked.connect(function() { - if (!gotoScript.isVisible()) { - showAddressBar(); - } else { - hideAddressBar(); - } - }); - - bubbleBtn = bottombar.addButton({ - icon: "icons/bubble-i.svg", - activeIcon: "icons/bubble-a.svg", - bgOpacity: 0, - hoverBgOpacity: 0, - activeBgOpacity: 0, - activeHoverBgOpacity: 0, - height: 240, - width: 294, - iconSize: 108, - textSize: 45, - text: "BUBBLE" - }); - - bubbleBtn.editProperties({isActive: Users.getIgnoreRadiusEnabled()}); - - bubbleBtn.clicked.connect(function() { - Users.toggleIgnoreRadius(); - bubbleBtn.editProperties({isActive: Users.getIgnoreRadiusEnabled()}); - }); - - loginBtn = bottombar.addButton({ - icon: "icons/login-i.svg", - activeIcon: "icons/login-a.svg", - height: 240, - width: 294, - iconSize: 108, - textSize: 45, - text: Account.isLoggedIn() ? "LOG OUT" : "LOG IN" - }); - loginBtn.clicked.connect(function() { - if (!Account.isLoggedIn()) { - Account.checkAndSignalForAccessToken(); - } else { - Menu.triggerOption("Login / Sign Up"); - } - }); - - // TODO: setup all the buttons or provide a dynamic interface - - raiseBottomBar(); - - -} - -var setupBottomHudOptionsBar = function() { - var bottomHud = new QmlFragment({ - qml: "hifi/bottomHudOptions.qml" - }); - - bottomHudOptionsBar = { - show: function() { - bottomHud.setVisible(true); - }, - hide: function() { - bottomHud.setVisible(false); - }, - qmlFragment: bottomHud - }; - bottomHud.fromQml.connect( - function(message) { - switch (message.method) { - case 'showUpBar': - printd('[bottombar.js] showUpBar message from bottomHudOptions.qml: ', JSON.stringify(message)); - raiseBottomBar(); - break; - default: - print('[bottombar.js] Unrecognized message from bottomHudOptions.qml:', JSON.stringify(message)); - } - } - ); -} - -function lowerBottomBar() { - if (bottombar) { - bottombar.setVisible(false); - } - if (bottomHudOptionsBar) { - bottomHudOptionsBar.show(); - } - Controller.setVPadExtraBottomMargin(0); -} - -function raiseBottomBar() { - print('[bottombar.js] raiseBottomBar begin'); - if (bottombar) { - bottombar.setVisible(true); - } - if (bottomHudOptionsBar) { - bottomHudOptionsBar.hide(); - } - Controller.setVPadExtraBottomMargin(255); // Height in bottombar.qml - print('[bottombar.js] raiseBottomBar end'); -} - -function showAddressBar() { - gotoScript.show(); - gotoBtn.isActive = true; -} - -function hideAddressBar() { - gotoScript.hide(); - gotoBtn.isActive = false; -} - -function showAvatarSelection() { - avatarSelection.show(); - avatarBtn.isActive = true; -} - -function hideAvatarSelection() { - avatarSelection.hide(); - avatarBtn.isActive = false; -} - -// TODO: Move to avatarSelection.js and make it possible to hide the window from there AND switch the button state here too -function processedNewAvatar(url, modelName) { - avatarSelection.refreshSelectedAvatar(url); - hideAvatarSelection(); -} - -function handleLogin() { - if (loginBtn) { - loginBtn.editProperties({text: "LOG OUT"}); - } -} - -function onUsernameChanged(username) { - if (Account.isLoggedIn()) { - MyAvatar.displayName = username; - } -} - -function handleLogout() { - MyAvatar.displayName = ""; - if (loginBtn) { - loginBtn.editProperties({text: "LOG IN"}); - } -} - -Script.scriptEnding.connect(function () { - shutdown(); - GlobalServices.connected.disconnect(handleLogin); - GlobalServices.disconnected.disconnect(handleLogout); - GlobalServices.myUsernameChanged.disconnect(onUsernameChanged); -}); - -init(); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/+android/goto.js b/scripts/system/+android/goto.js deleted file mode 100644 index 750844a2a4..0000000000 --- a/scripts/system/+android/goto.js +++ /dev/null @@ -1,108 +0,0 @@ -"use strict"; -// -// goto-android.js -// scripts/system/ -// -// Created by Gabriel Calero & Cristian Duarte on 12 Sep 2017 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var window; - - -var logEnabled = false; -function printd(str) { - if (logEnabled) - print("[goto-android.js] " + str); -} - -function init() { -} - -function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - switch (message.method) { - case 'shownChanged': - if (notifyShownChange) { - notifyShownChange(message.params.shown); - } ; - break; - case 'hide': - module.exports.hide(); - module.exports.onHidden(); - break; - case 'openAndroidActivity': - App.openAndroidActivity("Home"); - break; - default: - print('[goto-android.js] Unrecognized message from AddressBarDialog.qml:', JSON.stringify(message)); - } -} - -function sendToQml(message) { - window.sendToQml(message); -} - -var isVisible = false; -var qmlConnected = false; -var notifyShownChange; -module.exports = { - init: function() { - window = new QmlFragment({ - qml: "AddressBarDialog.qml", - visible: false - }); - }, - show: function() { - if (isVisible) return; - Controller.setVPadHidden(true); - if (window) { - if (!qmlConnected) { - window.fromQml.connect(fromQml); - qmlConnected = true; - } - window.setVisible(true); - isVisible = true; - } - }, - hide: function() { - if (!isVisible) return; - Controller.setVPadHidden(false); - if (window) { - if (qmlConnected) { - window.fromQml.disconnect(fromQml); - qmlConnected = false; - } - window.setVisible(false); - } - isVisible = false; - }, - destroy: function() { - if (window) { - window.close(); - window = null; - } - }, - isVisible: function() { - return isVisible; - }, - width: function() { - return window ? window.size.x : 0; - }, - height: function() { - return window ? window.size.y : 0; - }, - position: function() { - return window && isVisible ? window.position : null; - }, - setOnShownChange: function(f) { - notifyShownChange = f; - }, - onHidden: function() { } - - -}; - -init(); From ccb5e1e06c6627d8a109d5e2b72e8ce3e45e1298 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Mon, 23 Apr 2018 15:29:51 -0300 Subject: [PATCH 029/174] Commenting out display plugin activation/desactivation --- interface/src/Application.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d7f0db12c1..91712f9448 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7942,14 +7942,16 @@ void Application::openAndroidActivity(const QString& activityName) { void Application::enterBackground() { QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::BlockingQueuedConnection); - getActiveDisplayPlugin()->deactivate(); + //GC: commenting it out until we fix it + //getActiveDisplayPlugin()->deactivate(); } void Application::enterForeground() { QMetaObject::invokeMethod(DependencyManager::get().data(), "start", Qt::BlockingQueuedConnection); - if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { + //GC: commenting it out until we fix it + /*if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) { qWarning() << "Could not re-activate display plugin"; - } + }*/ } #endif From aceaa510c89a9226170de6c60dc7dd21505e50f7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 23 Apr 2018 14:47:17 -0700 Subject: [PATCH 030/174] Added referral to physical memory Test. Added menu items - `close` and `about` --- tools/auto-tester/src/Test.cpp | 78 +++++++++++++++++-------- tools/auto-tester/src/Test.h | 2 + tools/auto-tester/src/ui/AutoTester.cpp | 10 ++++ tools/auto-tester/src/ui/AutoTester.h | 2 + tools/auto-tester/src/ui/AutoTester.ui | 24 ++++++++ 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 99f9025fdd..57806e80f6 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -498,6 +498,12 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { const QString regexAssertGPU(ws + functionAssertGPU + ws + "\\(" + ws + quotedString + ".*"); const QRegularExpression lineAssertGPU = QRegularExpression(regexAssertGPU); + // Assert the correct amount of memory + const QString functionAssertPhysicalMemoryGB(ws + "autoTester" + ws + "\\." + ws + "assertPhysicalMemoryGB"); + const QString regexAssertPhysicalMemoryGB(ws + functionAssertPhysicalMemoryGB + ws + "\\(" + ws + quotedString + ".*"); + const QRegularExpression lineAssertPhysicalMemoryGB = QRegularExpression(regexAssertPhysicalMemoryGB); + + // Each step is either of the following forms: // autoTester.addStepSnapshot("Take snapshot"... // autoTester.addStep("Clean up after test"... @@ -514,18 +520,27 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { if (lineContainingTitle.match(line).hasMatch()) { QStringList tokens = line.split('"'); relevantTextFromTest.title = tokens[1]; + } else if (lineAssertPlatform.match(line).hasMatch()) { QStringList platforms = line.split('"'); relevantTextFromTest.platform = platforms[1]; + } else if (lineAssertDisplay.match(line).hasMatch()) { QStringList displays = line.split('"'); relevantTextFromTest.display = displays[1]; + } else if (lineAssertCPU.match(line).hasMatch()) { QStringList cpus = line.split('"'); relevantTextFromTest.cpu = cpus[1]; + } else if (lineAssertGPU.match(line).hasMatch()) { QStringList gpus = line.split('"'); relevantTextFromTest.gpu = gpus[1]; + + } else if (lineAssertPhysicalMemoryGB.match(line).hasMatch()) { + QStringList physicalMemoryGB = line.split('"'); + relevantTextFromTest.physicalMemoryGB = physicalMemoryGB[1]; + } else if (lineStepSnapshot.match(line).hasMatch()) { QStringList tokens = line.split('"'); QString nameOfStep = tokens[1]; @@ -534,6 +549,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { step->text = nameOfStep; step->takeSnapshot = true; relevantTextFromTest.stepList.emplace_back(step); + } else if (lineStep.match(line).hasMatch()) { QStringList tokens = line.split('"'); QString nameOfStep = tokens[1]; @@ -630,62 +646,74 @@ void Test::createMDFile(QString testDirectory) { // Platform QStringList platforms = testScriptLines.platform.split(" ");; - stream << "## Platforms\n"; - stream << "Run the test on each of the following platforms\n"; - for (int i = 0; i < platforms.size(); ++i) { - // Note that the platforms parameter may include extra spaces, these appear as empty strings in the list - if (platforms[i] != QString()) { - stream << " - " << platforms[i] << "\n"; + if (platforms.size() > 0) { + stream << "## Platforms\n"; + stream << "Run the test on each of the following platforms\n"; + for (int i = 0; i < platforms.size(); ++i) { + // Note that the platforms parameter may include extra spaces, these appear as empty strings in the list + if (platforms[i] != QString()) { + stream << " - " << platforms[i] << "\n"; + } } } // Display QStringList displays = testScriptLines.display.split(" "); - stream << "## Displays\n"; - stream << "Run the test on each of the following displays\n"; - for (int i = 0; i < displays.size(); ++i) { - // Note that the displays parameter may include extra spaces, these appear as empty strings in the list - if (displays[i] != QString()) { - stream << " - " << displays[i] << "\n"; + if (displays.size()) { + stream << "## Displays\n"; + stream << "Run the test on each of the following displays\n"; + for (int i = 0; i < displays.size(); ++i) { + // Note that the displays parameter may include extra spaces, these appear as empty strings in the list + if (displays[i] != QString()) { + stream << " - " << displays[i] << "\n"; + } } } // CPU QStringList cpus = testScriptLines.cpu.split(" "); - stream << "## Processors\n"; - stream << "Run the test on each of the following processors\n"; - for (int i = 0; i < cpus.size(); ++i) { - // Note that the cpus parameter may include extra spaces, these appear as empty strings in the list - if (cpus[i] != QString()) { - stream << " - " << cpus[i] << "\n"; + if (cpus.size() > 0) { + stream << "## Processors\n"; + stream << "Run the test on each of the following processors\n"; + for (int i = 0; i < cpus.size(); ++i) { + // Note that the cpus parameter may include extra spaces, these appear as empty strings in the list + if (cpus[i] != QString()) { + stream << " - " << cpus[i] << "\n"; + } } } // GPU QStringList gpus = testScriptLines.gpu.split(" "); - stream << "## Graphics Cards\n"; - stream << "Run the test on graphics cards from each of the following vendors\n"; - for (int i = 0; i < gpus.size(); ++i) { - // Note that the gpus parameter may include extra spaces, these appear as empty strings in the list - if (gpus[i] != QString()) { - stream << " - " << gpus[i] << "\n"; + if (gpus.size() > 0) { + stream << "## Graphics Cards\n"; + stream << "Run the test on graphics cards from each of the following vendors\n"; + for (int i = 0; i < gpus.size(); ++i) { + // Note that the gpus parameter may include extra spaces, these appear as empty strings in the list + if (gpus[i] != QString()) { + stream << " - " << gpus[i] << "\n"; + } } } stream << "## Steps\n"; stream << "Press space bar to advance step by step\n\n"; + // Note that snapshots of step n are taken in step n+1 + // (this implies that if the LAST step requests a snapshot then this will not work - caveat emptor) int snapShotIndex { 0 }; for (size_t i = 0; i < testScriptLines.stepList.size(); ++i) { stream << "### Step " << QString::number(i + 1) << "\n"; stream << "- " << testScriptLines.stepList[i]->text << "\n"; - if (testScriptLines.stepList[i]->takeSnapshot) { + if ((i + 1 < testScriptLines.stepList.size()) && testScriptLines.stepList[i + 1]->takeSnapshot) { stream << "- ![](./ExpectedImage_" << QString::number(snapShotIndex).rightJustified(5, '0') << ".png)\n"; ++snapShotIndex; } } mdFile.close(); + + messageBox.information(0, "Success", "Test MD file " + mdFilename + " has been created"); } void Test::createTestsOutline() { diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index e69459fef2..7f5553f9e3 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -34,6 +34,8 @@ public: QString display; QString cpu; QString gpu; + QString physicalMemoryGB; + StepList stepList; }; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 21acfe9569..3f7d2cba28 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -10,6 +10,8 @@ // #include "AutoTester.h" +#include + AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); ui.checkBoxInteractiveMode->setChecked(true); @@ -18,6 +20,9 @@ AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { test = new Test(); signalMapper = new QSignalMapper(); + + connect(ui.actionClose, &QAction::triggered, this, &AutoTester::on_closeButton_clicked); + connect(ui.actionAbout, &QAction::triggered, this, &AutoTester::about); } void AutoTester::on_evaluateTestsButton_clicked() { @@ -100,3 +105,8 @@ void AutoTester::saveImage(int index) { ui.progressBar->setValue(_numberOfImagesDownloaded); } } + +void AutoTester::about() { + QMessageBox messageBox; + messageBox.information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); +} \ No newline at end of file diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index 1788e97177..03cb7fbcec 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -37,6 +37,8 @@ private slots: void saveImage(int index); + void about(); + private: Ui::AutoTesterClass ui; Test* test; diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index 2eb1314481..c5115d69b2 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -157,6 +157,20 @@ 21 + + + File + + + + + + Help + + + + + @@ -167,6 +181,16 @@ + + + Close + + + + + About + + From b2925c5843ef5da8b40eb59adb8c12c94903f1c2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 24 Apr 2018 13:32:30 -0700 Subject: [PATCH 031/174] fixing attachments not being visible when coming out of first person --- interface/src/avatar/MyAvatar.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 249a765d92..e288528be9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2037,12 +2037,12 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { - + uint32_t renderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE; _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), - render::ItemKey::TAG_BITS_NONE, true); + renderTagBits, false); - _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(), - render::ItemKey::TAG_BITS_NONE, true); + _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(), + renderTagBits, false); } } } From 29fce488e479460437db366fdc2f5edb22e800bf Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 24 Apr 2018 14:00:52 -0700 Subject: [PATCH 032/174] make some changes --- interface/src/avatar/MyAvatar.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e288528be9..367042bcf9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2037,12 +2037,14 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { - uint32_t renderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE; - _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), - renderTagBits, false); + uint8_t modelRenderTagBits = shouldDrawHead ? render::ItemKey::TAG_BITS_0 : render::ItemKey::TAG_BITS_NONE; + modelRenderTagBits |= render::ItemKey::TAG_BITS_1; + _attachmentModels[i]->setVisibleInScene(true, qApp->getMain3DScene(), + modelRenderTagBits, false); - _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(), - renderTagBits, false); + uint8_t castShadowRenderTagBits = render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1; + _attachmentModels[i]->setCanCastShadow(true, qApp->getMain3DScene(), + castShadowRenderTagBits, false); } } } From 165c3214a75df8e9496023d92086672bd9deedf9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 24 Apr 2018 18:43:53 -0700 Subject: [PATCH 033/174] Avatar Scripts --- interface/src/Application.cpp | 29 +++++++++++++++++++ interface/src/avatar/MyAvatar.cpp | 13 +++++++++ interface/src/avatar/MyAvatar.h | 9 +++++- libraries/fbx/src/FBX.h | 1 + libraries/fbx/src/FSTReader.h | 1 + .../src/model-networking/ModelCache.cpp | 15 ++++++++++ 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d4c82d4bf..c1f77c792a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4724,6 +4724,35 @@ void Application::init() { avatar->setCollisionSound(sound); } }, Qt::QueuedConnection); + + connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToLoad, this, [this]() { + if (auto avatar = getMyAvatar()) { + auto scripts = avatar->getSkeletonModel()->getFBXGeometry().scripts; + if (scripts.size() > 0) { + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto script : scripts) { + int index = runningScripts.indexOf(script.toString()); + if (index < 0) { + auto loaded = scriptEngines->loadScript(script); + avatar->addScriptToUnload(script); + } + } + } + } + }, Qt::QueuedConnection); + + connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToUnload, this, [this]() { + if (auto avatar = getMyAvatar()) { + auto scripts = avatar->getScriptsToUnload(); + if (scripts.size() > 0) { + auto scriptEngines = DependencyManager::get(); + for (auto script : scripts) { + scriptEngines->stopScript(script.toString(), false); + } + } + } + }, Qt::QueuedConnection); } void Application::updateLOD(float deltaTime) const { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 249a765d92..2ba4a6afca 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -121,6 +121,7 @@ MyAvatar::MyAvatar(QThread* thread) : _skeletonModel = std::make_shared(this, nullptr); connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); + connect(_skeletonModel.get(), &Model::setURLFinished, this, &MyAvatar::setModelURLLoaded); connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); @@ -1463,6 +1464,9 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + if (_scriptsToUnload.size() > 0) { + emit avatarScriptsNeedToUnload(); + } _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); @@ -2384,6 +2388,11 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings settings.endGroup(); } +void MyAvatar::setModelURLLoaded() { + _scriptsToUnload.clear(); + emit avatarScriptsNeedToLoad(); +} + void MyAvatar::leaveDomain() { clearScaleRestriction(); saveAvatarScale(); @@ -2831,6 +2840,10 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } +void MyAvatar::addScriptToUnload(QUrl& scriptUrl) { + _scriptsToUnload.push_back(scriptUrl); +} + void MyAvatar::setSprintMode(bool sprint) { _walkSpeedScalar = sprint ? AVATAR_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6f82c7dfb9..38e189f92b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,6 +594,9 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; + void addScriptToUnload(QUrl& scriptUrl); + const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; + public slots: void increaseSize(); void decreaseSize(); @@ -659,10 +662,12 @@ signals: void sensorToWorldScaleChanged(float sensorToWorldScale); void attachmentsChanged(); void scaleChanged(); + void avatarScriptsNeedToLoad(); + void avatarScriptsNeedToUnload(); private slots: void leaveDomain(); - + void setModelURLLoaded(); protected: virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; @@ -905,6 +910,8 @@ private: // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; + + QVector _scriptsToUnload; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index a609d85fc8..d40511ce27 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -298,6 +298,7 @@ public: bool hasSkeletonJoints; QVector meshes; + QVector scripts; QHash materials; diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 981bae4feb..d1204c0876 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -28,6 +28,7 @@ static const QString TRANSLATION_Z_FIELD = "tz"; static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; static const QString BLENDSHAPE_FIELD = "bs"; +static const QString SCRIPT_FIELD = "script"; class FSTReader { public: diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index f17cdbb7e8..5a25bbc6fd 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -66,6 +66,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { auto mapping = FSTReader::readMapping(data); QString filename = mapping.value("filename").toString(); + if (filename.isNull()) { qCDebug(modelnetworking) << "Mapping file" << _url << "has no \"filename\" field"; finishedLoading(false); @@ -209,6 +210,20 @@ void GeometryReader::run() { throw QString("unsupported format"); } + if (_mapping.value("type").toString() == "body+head") { + auto scripts = _mapping.value("script"); + if (!scripts.isNull()) { + auto scriptsMap = scripts.toMap(); + auto count = scriptsMap.size(); + if (count > 0) { + for (auto &key : scriptsMap.keys()) { + auto scriptUrl = scriptsMap[key].toString(); + fbxGeometry->scripts.push_back(QUrl(scriptUrl)); + } + } + } + } + // Ensure the resource has not been deleted auto resource = _resource.toStrongRef(); if (!resource) { From eab7dd60067ff18bab4a3c2f7d7b6c618bcf2945 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 25 Apr 2018 10:25:34 +0200 Subject: [PATCH 034/174] Fixed procedural shaders --- libraries/render-utils/src/simple.slf | 10 ++++++++++ libraries/render-utils/src/simple_fade.slf | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index ed77777184..338f8607ee 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -16,7 +16,17 @@ // the interpolated normal in vec3 _normalWS; +in vec3 _normalMS; in vec4 _color; +in vec2 _texCoord0; +in vec4 _positionMS; +in vec4 _positionES; + +// For retro-compatibility +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES //PROCEDURAL_COMMON_BLOCK diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index 6e7aee2894..1cb4127e7b 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -19,9 +19,19 @@ // the interpolated normal in vec3 _normalWS; +in vec3 _normalMS; in vec4 _color; +in vec2 _texCoord0; +in vec4 _positionMS; +in vec4 _positionES; in vec4 _positionWS; +// For retro-compatibility +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES + //PROCEDURAL_COMMON_BLOCK #line 1001 From 328f1dec9be27258b154130f51681ece09b76c97 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 25 Apr 2018 18:56:18 +0200 Subject: [PATCH 035/174] Extended to other shaders --- libraries/render-utils/src/forward_simple.slf | 10 ++++++++++ .../render-utils/src/forward_simple_transparent.slf | 9 +++++++++ libraries/render-utils/src/simple.slf | 8 ++++---- libraries/render-utils/src/simple_fade.slf | 8 ++++---- libraries/render-utils/src/simple_transparent.slf | 10 ++++++++++ 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/forward_simple.slf b/libraries/render-utils/src/forward_simple.slf index 587fcbde73..1ac44750a7 100644 --- a/libraries/render-utils/src/forward_simple.slf +++ b/libraries/render-utils/src/forward_simple.slf @@ -16,11 +16,21 @@ <@include ForwardGlobalLight.slh@> <$declareEvalSkyboxGlobalColor()$> + // the interpolated normal in vec3 _normalWS; +in vec3 _normalMS; in vec4 _color; +in vec2 _texCoord0; +in vec4 _positionMS; in vec4 _positionES; +// For retro-compatibility +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES + layout(location = 0) out vec4 _fragColor0; //PROCEDURAL_COMMON_BLOCK diff --git a/libraries/render-utils/src/forward_simple_transparent.slf b/libraries/render-utils/src/forward_simple_transparent.slf index f40ba2ed4f..8be2759571 100644 --- a/libraries/render-utils/src/forward_simple_transparent.slf +++ b/libraries/render-utils/src/forward_simple_transparent.slf @@ -18,9 +18,18 @@ // the interpolated normal in vec3 _normalWS; +in vec3 _normalMS; in vec4 _color; +in vec2 _texCoord0; +in vec4 _positionMS; in vec4 _positionES; +// For retro-compatibility +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES + layout(location = 0) out vec4 _fragColor0; //PROCEDURAL_COMMON_BLOCK diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 338f8607ee..7591dc1882 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -23,10 +23,10 @@ in vec4 _positionMS; in vec4 _positionES; // For retro-compatibility -#define _normal _normalWS -#define _modelNormal _normalMS -#define _position _positionMS -#define _eyePosition _positionES +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES //PROCEDURAL_COMMON_BLOCK diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index 1cb4127e7b..0710c3e10b 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -27,10 +27,10 @@ in vec4 _positionES; in vec4 _positionWS; // For retro-compatibility -#define _normal _normalWS -#define _modelNormal _normalMS -#define _position _positionMS -#define _eyePosition _positionES +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES //PROCEDURAL_COMMON_BLOCK diff --git a/libraries/render-utils/src/simple_transparent.slf b/libraries/render-utils/src/simple_transparent.slf index c9815e8a80..ee79d2c0c4 100644 --- a/libraries/render-utils/src/simple_transparent.slf +++ b/libraries/render-utils/src/simple_transparent.slf @@ -16,7 +16,17 @@ // the interpolated normal in vec3 _normalWS; +in vec3 _normalMS; in vec4 _color; +in vec2 _texCoord0; +in vec4 _positionMS; +in vec4 _positionES; + +// For retro-compatibility +#define _normal _normalWS +#define _modelNormal _normalMS +#define _position _positionMS +#define _eyePosition _positionES //PROCEDURAL_COMMON_BLOCK From 44816941fce7644083171ca8c5b98f0005de3061 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 25 Apr 2018 10:57:57 -0700 Subject: [PATCH 036/174] Fix debug assert in manipulating thread local data to store GL surfaces --- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 45 +++++++++++++++++++---- libraries/gl/src/gl/OffscreenGLCanvas.h | 2 + 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index 4a2c5fd7f7..91f7954943 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -17,15 +17,18 @@ #include #include #include +#include +#include #include #include #include +#include + #include "Context.h" #include "GLHelpers.h" #include "GLLogging.h" - OffscreenGLCanvas::OffscreenGLCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface) @@ -33,6 +36,8 @@ OffscreenGLCanvas::OffscreenGLCanvas() : } OffscreenGLCanvas::~OffscreenGLCanvas() { + clearThreadContext(); + // A context with logging enabled needs to be current when it's destroyed _context->makeCurrent(_offscreenSurface); delete _context; @@ -117,25 +122,51 @@ QObject* OffscreenGLCanvas::getContextObject() { } void OffscreenGLCanvas::moveToThreadWithContext(QThread* thread) { + clearThreadContext(); moveToThread(thread); _context->moveToThread(thread); } -static const char* THREAD_CONTEXT_PROPERTY = "offscreenGlCanvas"; +struct ThreadContextStorage : public Dependency { + QThreadStorage> threadContext; +}; void OffscreenGLCanvas::setThreadContext() { - QThread::currentThread()->setProperty(THREAD_CONTEXT_PROPERTY, QVariant::fromValue(this)); + if (!DependencyManager::isSet()) { + DependencyManager::set(); + } + auto threadContextStorage = DependencyManager::get(); + QPointer p(this); + threadContextStorage->threadContext.setLocalData(p); +} + +void OffscreenGLCanvas::clearThreadContext() { + if (!DependencyManager::isSet()) { + return; + } + auto threadContextStorage = DependencyManager::get(); + if (!threadContextStorage->threadContext.hasLocalData()) { + return; + } + auto& threadContext = threadContextStorage->threadContext.localData(); + if (this != threadContext.operator OffscreenGLCanvas *()) { + return; + } + threadContextStorage->threadContext.setLocalData(nullptr); } bool OffscreenGLCanvas::restoreThreadContext() { // Restore the rendering context for this thread - auto threadCanvasVariant = QThread::currentThread()->property(THREAD_CONTEXT_PROPERTY); - if (!threadCanvasVariant.isValid()) { + if (!DependencyManager::isSet()) { return false; } - auto threadCanvasObject = qvariant_cast(threadCanvasVariant); - auto threadCanvas = static_cast(threadCanvasObject); + auto threadContextStorage = DependencyManager::get(); + if (!threadContextStorage->threadContext.hasLocalData()) { + return false; + } + + auto threadCanvas = threadContextStorage->threadContext.localData(); if (!threadCanvas) { return false; } diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.h b/libraries/gl/src/gl/OffscreenGLCanvas.h index ed644b98fb..a4960ae234 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.h +++ b/libraries/gl/src/gl/OffscreenGLCanvas.h @@ -39,6 +39,8 @@ private slots: void onMessageLogged(const QOpenGLDebugMessage &debugMessage); protected: + void clearThreadContext(); + std::once_flag _reportOnce; QOpenGLContext* _context{ nullptr }; QOffscreenSurface* _offscreenSurface{ nullptr }; From e0770f06b1eb27fcc5a8bd8db34ffb145bf0b3c5 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 25 Apr 2018 19:35:26 -0700 Subject: [PATCH 037/174] Add scripts to Model Packager --- interface/src/Application.cpp | 48 +++++++++---------- interface/src/Application.h | 3 ++ interface/src/ModelPackager.cpp | 30 ++++++++++-- interface/src/ModelPackager.h | 2 + interface/src/ModelPropertiesDialog.cpp | 19 ++++++++ interface/src/ModelPropertiesDialog.h | 2 + interface/src/avatar/MyAvatar.cpp | 20 ++++---- interface/src/avatar/MyAvatar.h | 9 ++-- libraries/fbx/src/FBX.h | 2 +- libraries/fbx/src/FSTReader.cpp | 4 +- .../src/model-networking/ModelCache.cpp | 23 +++++---- 11 files changed, 105 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1f77c792a..ad4cb56703 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2285,7 +2285,11 @@ void Application::onAboutToQuit() { // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); - + if (auto avatar = getMyAvatar()) { + auto urls = avatar->getScriptsToUnload(); + unloadAvatarScripts(urls); + } + _aboutToQuit = true; cleanupBeforeQuit(); @@ -4724,35 +4728,31 @@ void Application::init() { avatar->setCollisionSound(sound); } }, Qt::QueuedConnection); +} - connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToLoad, this, [this]() { - if (auto avatar = getMyAvatar()) { - auto scripts = avatar->getSkeletonModel()->getFBXGeometry().scripts; - if (scripts.size() > 0) { - auto scriptEngines = DependencyManager::get(); - auto runningScripts = scriptEngines->getRunningScripts(); - for (auto script : scripts) { - int index = runningScripts.indexOf(script.toString()); - if (index < 0) { - auto loaded = scriptEngines->loadScript(script); - avatar->addScriptToUnload(script); - } +void Application::loadAvatarScripts(const QVector& urls) { + if (auto avatar = getMyAvatar()) { + if (urls.size() > 0) { + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto url : urls) { + int index = runningScripts.indexOf(url); + if (index < 0) { + scriptEngines->loadScript(url); + avatar->addScriptToUnload(url); } } } - }, Qt::QueuedConnection); + } +} - connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToUnload, this, [this]() { - if (auto avatar = getMyAvatar()) { - auto scripts = avatar->getScriptsToUnload(); - if (scripts.size() > 0) { - auto scriptEngines = DependencyManager::get(); - for (auto script : scripts) { - scriptEngines->stopScript(script.toString(), false); - } - } +void Application::unloadAvatarScripts(const QVector& urls) { + if (urls.size() > 0) { + auto scriptEngines = DependencyManager::get(); + for (auto url : urls) { + scriptEngines->stopScript(url, false); } - }, Qt::QueuedConnection); + } } void Application::updateLOD(float deltaTime) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 74b0e5a110..2e91f842a4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -290,6 +290,9 @@ public: void replaceDomainContent(const QString& url); + void loadAvatarScripts(const QVector& urls); + void unloadAvatarScripts(const QVector& urls); + signals: void svoImportRequested(const QString& url); diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 5f4c7526e0..a87669bf47 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -156,9 +156,11 @@ bool ModelPackager::zipModel() { QByteArray nameField = _mapping.value(NAME_FIELD).toByteArray(); tempDir.mkpath(nameField + "/textures"); + tempDir.mkpath(nameField + "/scripts"); QDir fbxDir(tempDir.path() + "/" + nameField); QDir texDir(fbxDir.path() + "/textures"); - + QDir scriptDir(fbxDir.path() + "/scripts"); + // Copy textures listTextures(); if (!_textures.empty()) { @@ -166,6 +168,22 @@ bool ModelPackager::zipModel() { _texDir = _modelFile.path() + "/" + texdirField; copyTextures(_texDir, texDir); } + + // Copy scripts + QByteArray scriptField = _mapping.value(SCRIPT_FIELD).toByteArray(); + _mapping.remove(SCRIPT_FIELD); + if (scriptField.size() > 1) { + tempDir.mkpath(nameField + "/scripts"); + _scriptDir = _modelFile.path() + "/" + scriptField; + QDir wdir = QDir(_scriptDir); + _mapping.remove(SCRIPT_FIELD); + auto list = wdir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries); + for (auto script : list) { + auto sc = tempDir.relativeFilePath(scriptDir.path()) + "/" + QUrl(script).fileName(); + _mapping.insertMulti(SCRIPT_FIELD, sc); + } + copyDirectoryContent(wdir, scriptDir); + } // Copy LODs QVariantHash lodField = _mapping.value(LOD_FIELD).toHash(); @@ -189,7 +207,11 @@ bool ModelPackager::zipModel() { // Correct FST _mapping[FILENAME_FIELD] = tempDir.relativeFilePath(newPath); _mapping[TEXDIR_FIELD] = tempDir.relativeFilePath(texDir.path()); - + + for (auto multi : _mapping.values(SCRIPT_FIELD)) { + + multi.fromValue(tempDir.relativeFilePath(scriptDir.path()) + multi.toString()); + } // Copy FST QFile fst(tempDir.path() + "/" + nameField + ".fst"); if (fst.open(QIODevice::WriteOnly)) { @@ -237,7 +259,9 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename if (!mapping.contains(TEXDIR_FIELD)) { mapping.insert(TEXDIR_FIELD, "."); } - + if (!mapping.contains(SCRIPT_FIELD)) { + mapping.insert(SCRIPT_FIELD, "."); + } // mixamo/autodesk defaults if (!mapping.contains(SCALE_FIELD)) { mapping.insert(SCALE_FIELD, 1.0); diff --git a/interface/src/ModelPackager.h b/interface/src/ModelPackager.h index 10942833f9..60b3825c4d 100644 --- a/interface/src/ModelPackager.h +++ b/interface/src/ModelPackager.h @@ -37,10 +37,12 @@ private: QFileInfo _fbxInfo; FSTReader::ModelType _modelType; QString _texDir; + QString _scriptDir; QVariantHash _mapping; std::unique_ptr _geometry; QStringList _textures; + QStringList _scripts; }; diff --git a/interface/src/ModelPropertiesDialog.cpp b/interface/src/ModelPropertiesDialog.cpp index ae352974ae..35b07aa2b2 100644 --- a/interface/src/ModelPropertiesDialog.cpp +++ b/interface/src/ModelPropertiesDialog.cpp @@ -43,6 +43,9 @@ _geometry(geometry) form->addRow("Texture Directory:", _textureDirectory = new QPushButton()); connect(_textureDirectory, SIGNAL(clicked(bool)), SLOT(chooseTextureDirectory())); + form->addRow("Script Directory:", _scriptDirectory = new QPushButton()); + connect(_scriptDirectory, SIGNAL(clicked(bool)), SLOT(chooseScriptDirectory())); + form->addRow("Scale:", _scale = new QDoubleSpinBox()); _scale->setMaximum(FLT_MAX); _scale->setSingleStep(0.01); @@ -100,6 +103,7 @@ QVariantHash ModelPropertiesDialog::getMapping() const { mapping.insert(TYPE_FIELD, getType()); mapping.insert(NAME_FIELD, _name->text()); mapping.insert(TEXDIR_FIELD, _textureDirectory->text()); + mapping.insert(SCRIPT_FIELD, _scriptDirectory->text()); mapping.insert(SCALE_FIELD, QString::number(_scale->value())); // update the joint indices @@ -157,6 +161,7 @@ void ModelPropertiesDialog::reset() { _name->setText(_originalMapping.value(NAME_FIELD).toString()); _textureDirectory->setText(_originalMapping.value(TEXDIR_FIELD).toString()); _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble()); + _scriptDirectory->setText(_originalMapping.value(SCRIPT_FIELD).toString()); QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); @@ -207,6 +212,20 @@ void ModelPropertiesDialog::chooseTextureDirectory() { _textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1)); } +void ModelPropertiesDialog::chooseScriptDirectory() { + QString directory = QFileDialog::getExistingDirectory(this, "Choose Script Directory", + _basePath + "/" + _scriptDirectory->text()); + if (directory.isEmpty()) { + return; + } + if (!directory.startsWith(_basePath)) { + OffscreenUi::asyncWarning(NULL, "Invalid script directory", "Script directory must be child of base path."); + return; + } + _scriptDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1)); +} + + void ModelPropertiesDialog::updatePivotJoint() { _pivotJoint->setEnabled(!_pivotAboutCenter->isChecked()); } diff --git a/interface/src/ModelPropertiesDialog.h b/interface/src/ModelPropertiesDialog.h index 11abc5ab54..e3c2d8ed6a 100644 --- a/interface/src/ModelPropertiesDialog.h +++ b/interface/src/ModelPropertiesDialog.h @@ -37,6 +37,7 @@ public: private slots: void reset(); void chooseTextureDirectory(); + void chooseScriptDirectory(); void updatePivotJoint(); void createNewFreeJoint(const QString& joint = QString()); @@ -52,6 +53,7 @@ private: FBXGeometry _geometry; QLineEdit* _name = nullptr; QPushButton* _textureDirectory = nullptr; + QPushButton* _scriptDirectory = nullptr; QDoubleSpinBox* _scale = nullptr; QDoubleSpinBox* _translationX = nullptr; QDoubleSpinBox* _translationY = nullptr; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2ba4a6afca..69acf26477 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -121,7 +121,12 @@ MyAvatar::MyAvatar(QThread* thread) : _skeletonModel = std::make_shared(this, nullptr); connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); - connect(_skeletonModel.get(), &Model::setURLFinished, this, &MyAvatar::setModelURLLoaded); + connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) { + if (success) { + auto geometry = getSkeletonModel()->getFBXGeometry(); + qApp->loadAvatarScripts(geometry.scripts); + } + }); connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); @@ -1464,9 +1469,7 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - if (_scriptsToUnload.size() > 0) { - emit avatarScriptsNeedToUnload(); - } + qApp->unloadAvatarScripts(_scriptsToUnload); _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); @@ -2388,11 +2391,6 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings settings.endGroup(); } -void MyAvatar::setModelURLLoaded() { - _scriptsToUnload.clear(); - emit avatarScriptsNeedToLoad(); -} - void MyAvatar::leaveDomain() { clearScaleRestriction(); saveAvatarScale(); @@ -2840,8 +2838,8 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } -void MyAvatar::addScriptToUnload(QUrl& scriptUrl) { - _scriptsToUnload.push_back(scriptUrl); +void MyAvatar::addScriptToUnload(QString& url) { + _scriptsToUnload.push_back(url); } void MyAvatar::setSprintMode(bool sprint) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 38e189f92b..6e67defe6f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,8 +594,8 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; - void addScriptToUnload(QUrl& scriptUrl); - const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; + void addScriptToUnload(QString& url); + const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; public slots: void increaseSize(); @@ -662,12 +662,9 @@ signals: void sensorToWorldScaleChanged(float sensorToWorldScale); void attachmentsChanged(); void scaleChanged(); - void avatarScriptsNeedToLoad(); - void avatarScriptsNeedToUnload(); private slots: void leaveDomain(); - void setModelURLLoaded(); protected: virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; @@ -911,7 +908,7 @@ private: ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; - QVector _scriptsToUnload; + QVector _scriptsToUnload; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index d40511ce27..ce3fc52c3a 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -298,7 +298,7 @@ public: bool hasSkeletonJoints; QVector meshes; - QVector scripts; + QVector scripts; QHash materials; diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index cc4a919445..603f214c3e 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -84,7 +84,7 @@ void FSTReader::writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << TYPE_FIELD << SCALE_FIELD << FILENAME_FIELD - << TEXDIR_FIELD << JOINT_FIELD << FREE_JOINT_FIELD + << TEXDIR_FIELD << SCRIPT_FIELD << JOINT_FIELD << FREE_JOINT_FIELD << BLENDSHAPE_FIELD << JOINT_INDEX_FIELD; QBuffer buffer; buffer.open(QIODevice::WriteOnly); @@ -92,7 +92,7 @@ QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { for (auto key : PREFERED_ORDER) { auto it = mapping.find(key); if (it != mapping.constEnd()) { - if (key == FREE_JOINT_FIELD) { // writeVariant does not handle strings added using insertMulti. + if (key == FREE_JOINT_FIELD || key == SCRIPT_FIELD) { // writeVariant does not handle strings added using insertMulti. for (auto multi : mapping.values(key)) { buffer.write(key.toUtf8()); buffer.write(" = "); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 5a25bbc6fd..e3f543c403 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -210,16 +210,19 @@ void GeometryReader::run() { throw QString("unsupported format"); } - if (_mapping.value("type").toString() == "body+head") { - auto scripts = _mapping.value("script"); - if (!scripts.isNull()) { - auto scriptsMap = scripts.toMap(); - auto count = scriptsMap.size(); - if (count > 0) { - for (auto &key : scriptsMap.keys()) { - auto scriptUrl = scriptsMap[key].toString(); - fbxGeometry->scripts.push_back(QUrl(scriptUrl)); - } + // Store fst scripts on geometry + if (!_mapping.value(SCRIPT_FIELD).isNull()) { + QVariantList scripts = _mapping.values(SCRIPT_FIELD); + if (scripts.size() > 0) { + for (auto &script : scripts) { + QString scriptUrl = script.toString(); + if (QUrl(scriptUrl).isRelative()) { + if (scriptUrl.at(0) == '/') { + scriptUrl = scriptUrl.right(scriptUrl.length() - 1); + } + scriptUrl = _url.resolved(QUrl(scriptUrl)).toString(); + } + fbxGeometry->scripts.push_back(scriptUrl); } } } From 12f578c93c825feabf420b9f8548b597ad7b69d0 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 25 Apr 2018 19:46:31 -0700 Subject: [PATCH 038/174] More fixes --- interface/src/Application.cpp | 18 ++++++++---------- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ad4cb56703..c38bb9295a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4731,16 +4731,14 @@ void Application::init() { } void Application::loadAvatarScripts(const QVector& urls) { - if (auto avatar = getMyAvatar()) { - if (urls.size() > 0) { - auto scriptEngines = DependencyManager::get(); - auto runningScripts = scriptEngines->getRunningScripts(); - for (auto url : urls) { - int index = runningScripts.indexOf(url); - if (index < 0) { - scriptEngines->loadScript(url); - avatar->addScriptToUnload(url); - } + if (urls.size() > 0) { + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto url : urls) { + int index = runningScripts.indexOf(url); + if (index < 0) { + scriptEngines->loadScript(url); + getMyAvatar()->addScriptToUnload(url); } } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 69acf26477..462dbebbbb 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2838,7 +2838,7 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } -void MyAvatar::addScriptToUnload(QString& url) { +void MyAvatar::addScriptToUnload(const QString& url) { _scriptsToUnload.push_back(url); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6e67defe6f..00cb50e079 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,7 +594,7 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; - void addScriptToUnload(QString& url); + void addScriptToUnload(const QString& url); const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; public slots: From 496b638a885ef34cf66fe541e925aa61cef37b59 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Apr 2018 14:31:31 -0700 Subject: [PATCH 039/174] Fix log file directory not being capped at 50MB --- libraries/shared/src/shared/FileLogger.cpp | 35 +++++++++++----------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index 8ceb378574..4f4a9ab6dd 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -36,17 +36,15 @@ protected: private: const FileLogger& _logger; QMutex _fileMutex; - uint64_t _lastRollTime; + std::chrono::system_clock::time_point _lastRollTime; }; - - static const QString FILENAME_FORMAT = "hifi-log_%1%2.txt"; static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss"; static const QString LOGS_DIRECTORY = "Logs"; -static const QString IPADDR_WILDCARD = "[0-9]*.[0-9]*.[0-9]*.[0-9]*"; -static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[0,1][0-9]-[0-3][0-9]_[0-2][0-9].[0-6][0-9].[0-6][0-9]"; -static const QString FILENAME_WILDCARD = "hifi-log_" + IPADDR_WILDCARD + "_" + DATETIME_WILDCARD + ".txt"; +static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[01][0-9]-[0-3][0-9]_[0-2][0-9]\\.[0-6][0-9]\\.[0-6][0-9]"; +static const QString SESSION_WILDCARD = "[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}"; +static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\.txt" }; static QUuid SESSION_ID; // Max log size is 512 KB. We send log files to our crash reporter, so we want to keep this relatively @@ -104,20 +102,21 @@ void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfR _lastRollTime = now; } - QStringList nameFilters; - nameFilters << FILENAME_WILDCARD; - QDir logQDir(FileUtils::standardPath(LOGS_DIRECTORY)); - logQDir.setNameFilters(nameFilters); - logQDir.setSorting(QDir::Time); - QFileInfoList filesInDir = logQDir.entryInfoList(); + QDir logDir(FileUtils::standardPath(LOGS_DIRECTORY)); + logDir.setSorting(QDir::Time); + logDir.setFilter(QDir::Files); qint64 totalSizeOfDir = 0; - foreach(QFileInfo dirItm, filesInDir){ - if (totalSizeOfDir < MAX_LOG_DIR_SIZE){ - totalSizeOfDir += dirItm.size(); - } else { - QFile file(dirItm.filePath()); - file.remove(); + QFileInfoList filesInDir = logDir.entryInfoList(); + for (auto& fileInfo : filesInDir) { + if (!LOG_FILENAME_REGEX.exactMatch(fileInfo.fileName())) { + continue; + } + totalSizeOfDir += fileInfo.size(); + if (totalSizeOfDir > MAX_LOG_DIR_SIZE){ + qDebug() << "Removing log file: " << fileInfo.fileName(); + QFile oldLogFile(fileInfo.filePath()); + oldLogFile.remove(); } } } From 1448f3959ebe541fe9457e70b2aae0e0598e6b04 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Thu, 26 Apr 2018 17:11:17 -0700 Subject: [PATCH 040/174] Add a utility function to dump ConnectionStats --- .../networking/src/udt/ConnectionStats.cpp | 29 +++++++++++++++++++ .../networking/src/udt/ConnectionStats.h | 3 ++ 2 files changed, 32 insertions(+) diff --git a/libraries/networking/src/udt/ConnectionStats.cpp b/libraries/networking/src/udt/ConnectionStats.cpp index e7efe3d5af..46d88e680f 100644 --- a/libraries/networking/src/udt/ConnectionStats.cpp +++ b/libraries/networking/src/udt/ConnectionStats.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include "ConnectionStats.h" using namespace udt; @@ -112,3 +113,31 @@ void ConnectionStats::recordPacketSendPeriod(int sample) { _currentSample.packetSendPeriod = sample; _total.packetSendPeriod = (int)((_total.packetSendPeriod * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT)); } + +QDebug& operator<<(QDebug&& debug, const udt::ConnectionStats::Stats& stats) { + debug << "Connection stats:\n"; +#define HIFI_LOG_EVENT(x) << " " #x " events: " << stats.events[ConnectionStats::Stats::Event::x] << "\n" + debug + HIFI_LOG_EVENT(SentACK) + HIFI_LOG_EVENT(ReceivedACK) + HIFI_LOG_EVENT(ProcessedACK) + HIFI_LOG_EVENT(SentLightACK) + HIFI_LOG_EVENT(ReceivedLightACK) + HIFI_LOG_EVENT(SentACK2) + HIFI_LOG_EVENT(ReceivedACK2) + HIFI_LOG_EVENT(SentNAK) + HIFI_LOG_EVENT(ReceivedNAK) + HIFI_LOG_EVENT(SentTimeoutNAK) + HIFI_LOG_EVENT(ReceivedTimeoutNAK) + HIFI_LOG_EVENT(Retransmission) + HIFI_LOG_EVENT(Duplicate) + ; +#undef HIFI_LOG_EVENT + + debug << " Sent packets: " << stats.sentPackets; + debug << "\n Received packets: " << stats.receivedPackets; + debug << "\n Sent util bytes: " << stats.sentUtilBytes; + debug << "\n Sent bytes: " << stats.sentBytes; + debug << "\n Received bytes: " << stats.receivedBytes << "\n"; + return debug; +} diff --git a/libraries/networking/src/udt/ConnectionStats.h b/libraries/networking/src/udt/ConnectionStats.h index 84cd6b2486..7ec7b163ee 100644 --- a/libraries/networking/src/udt/ConnectionStats.h +++ b/libraries/networking/src/udt/ConnectionStats.h @@ -101,4 +101,7 @@ private: } +class QDebug; +QDebug& operator<<(QDebug&& debug, const udt::ConnectionStats::Stats& stats); + #endif // hifi_ConnectionStats_h From 290c31d9162a6e81adbf57530feeff9393d2c732 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 27 Apr 2018 11:33:45 -0700 Subject: [PATCH 041/174] don't spam resetSensors --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38caca090..18ba4958aa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3554,7 +3554,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { showCursor(Cursor::Icon::DEFAULT); } - } else { + } else if (!event->isAutoRepeat()){ resetSensors(true); } break; From cf9b089a3c523c26fbe0a60ee142702ee5969971 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Apr 2018 17:18:16 -0700 Subject: [PATCH 042/174] Added option to set snapshot location (for this execution only) from the command line. --- interface/src/Application.cpp | 15 ++++++++++++--- interface/src/Application.h | 2 ++ interface/src/ui/Snapshot.cpp | 12 +++++++++--- interface/src/ui/Snapshot.h | 4 ++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38caca090..c0fe84894d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -986,13 +986,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); { - const QString TEST_SCRIPT = "--testScript"; + const QString TEST_SCRIPT { "--testScript" }; + const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; + const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT) { QString testScriptPath = args.at(i + 1); if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); + } + } else if (args.at(i) == TEST_SNAPSHOT_LOCATION) { + // Set test snapshot location only if it is a writeable directory + QString pathname(args.at(i + 1)); + QFileInfo fileInfo(pathname); + if (fileInfo.isDir() && fileInfo.isWritable()) { + testSnapshotLocation = pathname; } } } @@ -7259,7 +7268,7 @@ void Application::loadAvatarBrowser() const { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { // Get a screenshot and save it - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, QString()); // If we're not doing an animated snapshot as well... if (!includeAnimated) { // Tell the dependency manager that the capture of the still snapshot has taken place. @@ -7273,7 +7282,7 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa void Application::takeSecondaryCameraSnapshot(const QString& filename) { postLambdaEvent([filename, this] { - QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename); + QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename, testSnapshotLocation); emit DependencyManager::get()->stillSnapshotTaken(snapshotPath, true); }); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 74b0e5a110..341560bc5b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -719,5 +719,7 @@ private: std::atomic _pendingIdleEvent { true }; std::atomic _pendingRenderEvent { true }; + + QString testSnapshotLocation { QString() }; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 69103a40b5..9eb64dcb14 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -89,10 +89,10 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename) { QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { // return whatever we get back from saved file for snapshot - return static_cast(savedFileForSnapshot(image, true)); + return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } -QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename) { +QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname) { // adding URL to snapshot QUrl currentURL = DependencyManager::get()->currentPublicAddress(); @@ -117,7 +117,13 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt const int IMAGE_QUALITY = 100; if (!isTemporary) { - QString snapshotFullPath = snapshotsLocation.get(); + // If user has requested specific path then use it, else use the application value + QString snapshotFullPath; + if (!userSelectedPathname.isNull()) { + snapshotFullPath = userSelectedPathname; + } else { + snapshotFullPath = snapshotsLocation.get(); + } if (snapshotFullPath.isEmpty()) { snapshotFullPath = OffscreenUi::getExistingDirectory(nullptr, "Choose Snapshots Directory", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 62d3ed3db8..20e9e8339f 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -37,7 +37,7 @@ class Snapshot : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: - static QString saveSnapshot(QImage image, const QString& filename); + static QString saveSnapshot(QImage image, const QString& filename, const QString& pathname); static QTemporaryFile* saveTempSnapshot(QImage image); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); @@ -51,7 +51,7 @@ public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); private: - static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename = QString()); + static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname); }; #endif // hifi_Snapshot_h From 2cc3ed6287afbd5df4cb65a6f42f6389671eeabe Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 28 Apr 2018 20:00:28 +1200 Subject: [PATCH 043/174] List which contexts each namespace and object is available in --- interface/src/AvatarBookmarks.h | 4 ++++ interface/src/LODManager.h | 5 ++++- interface/src/SpeechRecognizer.h | 3 +++ interface/src/audio/AudioScope.h | 4 ++++ interface/src/avatar/AvatarManager.h | 3 +++ interface/src/devices/DdeFaceTracker.h | 3 +++ interface/src/raypick/PickScriptingInterface.h | 4 ++++ interface/src/raypick/PointerScriptingInterface.h | 3 +++ .../src/scripting/AccountServicesScriptingInterface.h | 3 +++ interface/src/scripting/Audio.h | 8 +++++++- interface/src/scripting/ClipboardScriptingInterface.h | 3 +++ .../src/scripting/ControllerScriptingInterface.h | 5 ++++- .../src/scripting/GooglePolyScriptingInterface.h | 3 +++ interface/src/scripting/HMDScriptingInterface.h | 6 +++++- interface/src/scripting/MenuScriptingInterface.h | 3 +++ interface/src/scripting/SelectionScriptingInterface.h | 3 +++ interface/src/scripting/SettingsScriptingInterface.h | 3 +++ interface/src/scripting/WindowScriptingInterface.h | 6 +++++- interface/src/ui/AvatarInputs.h | 4 ++++ interface/src/ui/overlays/ContextOverlayInterface.h | 3 --- interface/src/ui/overlays/Overlays.h | 4 ++++ libraries/animation/src/AnimationCache.h | 4 ++++ libraries/audio-client/src/AudioIOStats.h | 8 ++++++++ libraries/audio/src/SoundCache.h | 5 +++++ .../src/controllers/impl/MappingBuilderProxy.h | 5 ++++- .../src/controllers/impl/RouteBuilderProxy.h | 3 +++ .../src/display-plugins/CompositorHelper.h | 4 ++++ libraries/entities/src/EntityScriptingInterface.h | 6 ++++++ .../graphics-scripting/GraphicsScriptingInterface.h | 3 +++ .../src/model-networking/ModelCache.h | 3 +++ .../src/model-networking/TextureCache.h | 3 +++ libraries/networking/src/AddressManager.h | 5 +++++ libraries/networking/src/MessagesClient.h | 5 +++++ libraries/networking/src/ResourceCache.h | 6 ++++++ libraries/script-engine/src/AssetScriptingInterface.h | 5 +++++ libraries/script-engine/src/Quat.h | 6 ++++++ .../script-engine/src/RecordingScriptingInterface.h | 4 ++++ libraries/script-engine/src/SceneScriptingInterface.h | 8 ++++++++ libraries/script-engine/src/ScriptEngine.h | 6 ++++++ libraries/script-engine/src/ScriptEngines.h | 4 ++++ libraries/script-engine/src/ScriptUUID.h | 6 ++++++ libraries/script-engine/src/ScriptsModel.h | 3 +++ libraries/script-engine/src/ScriptsModelFilter.h | 3 +++ libraries/script-engine/src/UsersScriptingInterface.h | 7 ++++++- libraries/script-engine/src/Vec3.h | 6 ++++++ libraries/shared/src/DebugDraw.h | 5 +++++ libraries/shared/src/PathUtils.h | 4 ++++ libraries/shared/src/RegisteredMetaTypes.h | 6 ++++++ libraries/shared/src/shared/Camera.h | 4 ++++ libraries/ui/src/ui/TabletScriptingInterface.h | 11 +++++++++++ 50 files changed, 221 insertions(+), 10 deletions(-) diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 177e6e493e..7b47ea8af7 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -18,6 +18,10 @@ /**jsdoc * This API helps manage adding and deleting avatar bookmarks. * @namespace AvatarBookmarks + * + * @hifi-interface + * @hifi-client-entity + * */ class AvatarBookmarks: public Bookmarks, public Dependency { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index e8737d92ae..889fff3153 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -10,8 +10,11 @@ // /**jsdoc - * The LOD class manages your Level of Detail functions within interface + * The LODManager API manages your Level of Detail functions within interface. * @namespace LODManager + * + * @hifi-interface + * @hifi-client-entity */ #ifndef hifi_LODManager_h diff --git a/interface/src/SpeechRecognizer.h b/interface/src/SpeechRecognizer.h index d5f9031cfc..b22ab73837 100644 --- a/interface/src/SpeechRecognizer.h +++ b/interface/src/SpeechRecognizer.h @@ -24,6 +24,9 @@ /**jsdoc * @namespace SpeechRecognizer + * + * @hifi-interface + * @hifi-client-entity */ class SpeechRecognizer : public QObject, public Dependency { Q_OBJECT diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index ff8bfda6dd..41cee8d17d 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -28,6 +28,10 @@ class AudioScope : public QObject, public Dependency { /**jsdoc * The AudioScope API helps control the Audio Scope features in Interface * @namespace AudioScope + * + * @hifi-interface + * @hifi-client-entity + * * @property {number} scopeInput Read-only. * @property {number} scopeOutputLeft Read-only. * @property {number} scopeOutputRight Read-only. diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index d2655914d2..7f5aa00466 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -30,6 +30,9 @@ /**jsdoc * The AvatarManager API has properties and methods which manage Avatars within the same domain. * @namespace AvatarManager + * + * @hifi-interface + * @hifi-client-entity */ class AvatarManager : public AvatarHashMap { diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index d4af0bbd37..4fe36b582e 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -29,6 +29,9 @@ /**jsdoc * The FaceTracker API helps manage facial tracking hardware. * @namespace FaceTracker + * + * @hifi-interface + * @hifi-client-entity */ class DdeFaceTracker : public FaceTracker, public Dependency { diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index f2cd9287a5..2568dd8457 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -18,6 +18,10 @@ * The Picks API lets you create and manage objects for repeatedly calculating intersections in different ways. * * @namespace Picks + * + * @hifi-interface + * @hifi-client-entity + * * @property PICK_NOTHING {number} A filter flag. Don't intersect with anything. * @property PICK_ENTITIES {number} A filter flag. Include entities when intersecting. * @property PICK_OVERLAYS {number} A filter flag. Include overlays when intersecting. diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 1cc7b56503..e7acfd4037 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -19,6 +19,9 @@ * Pointers can also be configured to automatically generate PointerEvents. * * @namespace Pointers + * + * @hifi-interface + * @hifi-client-entity */ class PointerScriptingInterface : public QObject, public Dependency { diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index d38a84d8fa..5774ee1da5 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -38,6 +38,9 @@ class AccountServicesScriptingInterface : public QObject { /**jsdoc * The AccountServices API contains helper functions related to user connectivity * + * @hifi-interface + * @hifi-client-entity + * * @namespace AccountServices * @property {string} username Read-only. * @property {boolean} loggedIn Read-only. diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index c77d1522b5..f0a4328c2f 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -27,8 +27,14 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { /**jsdoc * The Audio API features tools to help control audio contexts and settings. - * + * * @namespace Audio + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property {boolean} muted * @property {boolean} noiseReduction * @property {number} inputVolume diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index cce300e831..32b8c64a7d 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -21,6 +21,9 @@ * The Clipboard API enables you to export and import entities to and from JSON files. * * @namespace Clipboard + * + * @hifi-interface + * @hifi-client-entity */ class ClipboardScriptingInterface : public QObject { Q_OBJECT diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index f19caa8478..42bb648abf 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -145,7 +145,10 @@ class ScriptEngine; * * @namespace Controller * - * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end + * @hifi-interface + * @hifi-client-entity + * + * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end * points in a {@link RouteObject} mapping. A synonym for Controller.Hardware.Actions. * Read-only.
* Default mappings are provided from the Controller.Hardware.Keyboard and Controller.Standard to diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 5c37b394fa..fb5aed9759 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -18,6 +18,9 @@ /**jsdoc * The GooglePoly API allows you to interact with Google Poly models direct from inside High Fidelity. * @namespace GooglePoly + * + * @hifi-interface + * @hifi-client-entity */ class GooglePolyScriptingInterface : public QObject, public Dependency { diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 9b2482e73a..d2a272851f 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -28,7 +28,11 @@ class QScriptEngine; * The HMD API provides access to the HMD used in VR display mode. * * @namespace HMD - * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise + * + * @hifi-interface + * @hifi-client-entity + * + * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise * {@link Vec3(0)|Vec3.ZERO}. Read-only. * @property {Quat} orientation - The orientation of the HMD if currently in VR display mode, otherwise * {@link Quat(0)|Quat.IDENTITY}. Read-only. diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 649c444eaf..81cf775de8 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -32,6 +32,9 @@ class MenuItemProperties; * If a menu item doesn't belong to a group it is always displayed. * * @namespace Menu + * + * @hifi-interface + * @hifi-client-entity */ /** diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 71ff41248a..df92250c28 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -86,6 +86,9 @@ protected: * The Selection API provides a means of grouping together avatars, entities, and overlays in named lists. * @namespace Selection * + * @hifi-interface + * @hifi-client-entity + * * @example Outline an entity when it is grabbed by a controller. * // Create a box and copy the following text into the entity's "Script URL" field. * (function () { diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h index 9e0271601b..32d868bb24 100644 --- a/interface/src/scripting/SettingsScriptingInterface.h +++ b/interface/src/scripting/SettingsScriptingInterface.h @@ -18,6 +18,9 @@ /**jsdoc * The Settings API provides a facility to store and retrieve values that persist between Interface runs. * @namespace Settings + * + * @hifi-interface + * @hifi-client-entity */ class SettingsScriptingInterface : public QObject { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 0b766d2097..348882e0f8 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -28,7 +28,11 @@ * physics. * * @namespace Window - * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other + * + * @hifi-interface + * @hifi-client-entity + * + * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other * chrome), in pixels. Read-only. * @property {number} innerHeight - The height of the drawable area of the Interface window (i.e., without borders or other * chrome), in pixels. Read-only. diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h index a9d1509770..e67d35e59f 100644 --- a/interface/src/ui/AvatarInputs.h +++ b/interface/src/ui/AvatarInputs.h @@ -26,6 +26,10 @@ class AvatarInputs : public QObject { /**jsdoc * API to help manage your Avatar's input * @namespace AvatarInputs + * + * @hifi-interface + * @hifi-client-entity + * * @property {boolean} cameraEnabled Read-only. * @property {boolean} cameraMuted Read-only. * @property {boolean} isHMD Read-only. diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index b80a3a70fb..808c3a4ee3 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -31,9 +31,6 @@ #include "EntityTree.h" #include "ContextOverlayLogging.h" -/**jsdoc -* @namespace ContextOverlay -*/ class ContextOverlayInterface : public QObject, public Dependency { Q_OBJECT diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index c2f6e3e693..cf1151b46a 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -76,6 +76,10 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R * The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to * yourself and that aren't persisted to the domain. They are used for UI. * @namespace Overlays + * + * @hifi-interface + * @hifi-client-entity + * * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Overlays.OverlayType|web3d} overlay that has keyboard focus. * If no overlay has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to * clear keyboard focus. diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 03b37aef2f..4db009f592 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -37,6 +37,10 @@ public: * API to manage animation cache resources. * @namespace AnimationCache * + * @hifi-interface + * @hifi-client-entity + * @hifi-assignment-client + * * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. * @property {number} sizeTotal - Size in bytes of all resources. Read-only. diff --git a/libraries/audio-client/src/AudioIOStats.h b/libraries/audio-client/src/AudioIOStats.h index 89db4942ec..45fcf365da 100644 --- a/libraries/audio-client/src/AudioIOStats.h +++ b/libraries/audio-client/src/AudioIOStats.h @@ -41,6 +41,10 @@ class AudioStreamStatsInterface : public QObject { /**jsdoc * @class AudioStats.AudioStreamStats + * + * @hifi-interface + * @hifi-client-entity + * * @property {number} lossRate Read-only. * @property {number} lossCount Read-only. * @property {number} lossRateWindow Read-only. @@ -185,6 +189,10 @@ class AudioStatsInterface : public QObject { /**jsdoc * Audio stats from the client. * @namespace AudioStats + * + * @hifi-interface + * @hifi-client-entity + * * @property {number} pingMs Read-only. * @property {number} inputReadMsMax Read-only. * @property {number} inputUnplayedMsMax Read-only. diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h index d8c52635e0..0874cef90e 100644 --- a/libraries/audio/src/SoundCache.h +++ b/libraries/audio/src/SoundCache.h @@ -29,6 +29,11 @@ public: * API to manage sound cache resources. * @namespace SoundCache * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. * @property {number} sizeTotal - Size in bytes of all resources. Read-only. diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 86a43c0c13..4521c89afd 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -49,9 +49,12 @@ class UserInputMapper; * output that already has a route the new route is ignored. *
  • New mappings override previous mappings: each output is processed using the route in the most recently enabled * mapping that contains that output.
  • - *

    + * * * @class MappingObject + * + * @hifi-interface + * @hifi-client-entity */ /**jsdoc diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 0336638068..3204e0502f 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -35,6 +35,9 @@ class ScriptingInterface; * types.

    * * @class RouteObject + * + * @hifi-interface + * @hifi-client-entity */ // TODO migrate functionality to a RouteBuilder class and make the proxy defer to that diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index bc6ed63363..fb712c26fa 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -174,6 +174,10 @@ private: /**jsdoc * @namespace Reticle + * + * @hifi-interface + * @hifi-client-entity + * * @property {boolean} allowMouseCapture * @property {number} depth * @property {Vec2} maximumPosition diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index d4a8b11453..2491d4bbbd 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -94,6 +94,12 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra * Interface has displayed and so knows about. * * @namespace Entities + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property {Uuid} keyboardFocusEntity - Get or set the {@link Entities.EntityType|Web} entity that has keyboard focus. * If no entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to * clear keyboard focus. diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 526352804b..8b76491229 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -24,6 +24,9 @@ /**jsdoc * The experimental Graphics API (experimental) lets you query and manage certain graphics-related structures (like underlying meshes and textures) from scripting. * @namespace Graphics + * + * @hifi-interface + * @hifi-client-entity */ class GraphicsScriptingInterface : public QObject, public QScriptable, public Dependency { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 9532f39ce0..cda825e5fb 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -144,6 +144,9 @@ public: * API to manage model cache resources. * @namespace ModelCache * + * @hifi-interface + * @hifi-client-entity + * * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. * @property {number} sizeTotal - Size in bytes of all resources. Read-only. diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 3f46dc3074..ef911103c3 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -151,6 +151,9 @@ public: * API to manage texture cache resources. * @namespace TextureCache * + * @hifi-interface + * @hifi-client-entity + * * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. * @property {number} sizeTotal - Size in bytes of all resources. Read-only. diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 94eff46bda..94fb25812f 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -33,6 +33,11 @@ const QString GET_PLACE = "/api/v1/places/%1"; * The location API provides facilities related to your current location in the metaverse. * * @namespace location + * + * @hifi-interface + * @hifi-client-entity + * @hifi-assignment-client + * * @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not * connected to the domain or are in a serverless domain. * Read-only. diff --git a/libraries/networking/src/MessagesClient.h b/libraries/networking/src/MessagesClient.h index 6ef3777d8c..f2ccfe33f4 100644 --- a/libraries/networking/src/MessagesClient.h +++ b/libraries/networking/src/MessagesClient.h @@ -37,6 +37,11 @@ * * * @namespace Messages + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client */ class MessagesClient : public QObject, public Dependency { Q_OBJECT diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 609483bc56..799d2c7f59 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -89,6 +89,12 @@ class ScriptableResource : public QObject { /**jsdoc * @constructor Resource + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property {string} url - URL of this resource. * @property {Resource.State} state - Current loading state. */ diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 5cb1136b74..eb9a628ae3 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -27,6 +27,11 @@ /**jsdoc * The Assets API allows you to communicate with the Asset Browser. * @namespace Assets + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client */ class AssetScriptingInterface : public BaseAssetScriptingInterface, QScriptable { Q_OBJECT diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index e6e395d9bf..254757dece 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -35,6 +35,12 @@ * of gimbal lock. * @namespace Quat * @variation 0 + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property IDENTITY {Quat} { x: 0, y: 0, z: 0, w: 1 } : The identity rotation, i.e., no rotation. * Read-only. * @example Print the IDENTITY value. diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/script-engine/src/RecordingScriptingInterface.h index 0e4f90b928..29d9b31049 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.h +++ b/libraries/script-engine/src/RecordingScriptingInterface.h @@ -25,6 +25,10 @@ class QScriptValue; /**jsdoc * @namespace Recording + * + * @hifi-interface + * @hifi-client-entity + * @hifi-assignment-client */ class RecordingScriptingInterface : public QObject, public Dependency { Q_OBJECT diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index c69cd7090d..fdfbc6f6c0 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -112,6 +112,10 @@ namespace SceneScripting { /**jsdoc * @class Scene.Stage + * + * @hifi-interface + * @hifi-client-entity + * * @property {string} backgroundMode * @property {Scene.Stage.KeyLight} keyLight * @property {Scene.Stage.Location} location @@ -171,6 +175,10 @@ namespace SceneScripting { /**jsdoc * @namespace Scene + * + * @hifi-interface + * @hifi-client-entity + * * @property {boolean} shouldRenderAvatars * @property {boolean} shouldRenderEntities * @property {Scene.Stage} stage diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 63a4ba4f90..af4d04a706 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -89,6 +89,12 @@ public: /**jsdoc * @namespace Script + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property {string} context */ class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 1200168420..da6fe521c9 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -29,6 +29,10 @@ class ScriptEngine; /**jsdoc * @namespace ScriptDiscoveryService + * + * @hifi-interface + * @hifi-client-entity + * * @property {string} debugScriptUrl * @property {string} defaultScriptsPath * @property {ScriptsModel} scriptsModel diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h index 303a871d1d..9b61f451c5 100644 --- a/libraries/script-engine/src/ScriptUUID.h +++ b/libraries/script-engine/src/ScriptUUID.h @@ -23,6 +23,12 @@ * hexadecimal digits. * * @namespace Uuid + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property NULL {Uuid} The null UUID, {00000000-0000-0000-0000-000000000000}. */ diff --git a/libraries/script-engine/src/ScriptsModel.h b/libraries/script-engine/src/ScriptsModel.h index a4ffc192f9..2466347baa 100644 --- a/libraries/script-engine/src/ScriptsModel.h +++ b/libraries/script-engine/src/ScriptsModel.h @@ -68,6 +68,9 @@ public: *

    Has properties and functions below in addition to those of * http://doc.qt.io/qt-5/qabstractitemmodel.html.

    * @class ScriptsModel + * + * @hifi-interface + * @hifi-client-entity */ class ScriptsModel : public QAbstractItemModel { Q_OBJECT diff --git a/libraries/script-engine/src/ScriptsModelFilter.h b/libraries/script-engine/src/ScriptsModelFilter.h index 26efde02e8..05a76334bb 100644 --- a/libraries/script-engine/src/ScriptsModelFilter.h +++ b/libraries/script-engine/src/ScriptsModelFilter.h @@ -20,6 +20,9 @@ *

    Has properties and functions per * http://doc.qt.io/qt-5/qsortfilterproxymodel.html.

    * @class ScriptsModelFilter + * + * @hifi-interface + * @hifi-client-entity */ class ScriptsModelFilter : public QSortFilterProxyModel { Q_OBJECT diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 6728c471f6..f214c3f11c 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -18,7 +18,12 @@ /**jsdoc * @namespace Users - * @property {boolean} canKick - true if the domain server allows the node or avatar to kick (ban) avatars, + * + * @hifi-interface + * @hifi-client-entity + * @hifi-assignment-client + * + * @property {boolean} canKick - true if the domain server allows the node or avatar to kick (ban) avatars, * otherwise false. Read-only. * @property {boolean} requestsDomainListData - true if the avatar requests extra data from the mixers (such as * positional data of an avatar you've ignored). Read-only. diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index 635f2a530c..eb9438c5c2 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -47,6 +47,12 @@ * * @namespace Vec3 * @variation 0 + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @property {Vec3} UNIT_X - { x: 1, y: 0, z: 0 } : Unit vector in the x-axis direction. Read-only. * @property {Vec3} UNIT_Y - { x: 0, y: 1, z: 0 } : Unit vector in the y-axis direction. Read-only. * @property {Vec3} UNIT_Z - { x: 0, y: 0, z: 1 } : Unit vector in the z-axis direction. Read-only. diff --git a/libraries/shared/src/DebugDraw.h b/libraries/shared/src/DebugDraw.h index 64327585fb..7dd19415c9 100644 --- a/libraries/shared/src/DebugDraw.h +++ b/libraries/shared/src/DebugDraw.h @@ -25,6 +25,11 @@ * Helper functions to render ephemeral debug markers and lines. * DebugDraw markers and lines are only visible locally, they are not visible by other users. * @namespace DebugDraw + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client */ class DebugDraw : public QObject { Q_OBJECT diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index d879ac968d..fc933b6b8c 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -22,6 +22,10 @@ * The Paths API provides absolute paths to the scripts and resources directories. * * @namespace Paths + * + * @hifi-interface + * @hifi-client-entity + * * @deprecated The Paths API is deprecated. Use {@link Script.resolvePath} and {@link Script.resourcesPath} instead. * @readonly * @property {string} defaultScripts - The path to the scripts directory. Read-only. diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 689d1a3f42..467d6374a5 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -361,6 +361,12 @@ using MeshPointer = std::shared_ptr; /**jsdoc * A handle for a mesh in an entity, such as returned by {@link Entities.getMeshes}. * @class MeshProxy + * + * @hifi-interface + * @hifi-client-entity + * @hifi-server-entity + * @hifi-assignment-client + * * @deprecated Use the {@link Graphics} API instead. */ class MeshProxy : public QObject { diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index ea2e9cddab..32e753d0f9 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -40,6 +40,10 @@ class Camera : public QObject { * The Camera API provides access to the "camera" that defines your view in desktop and HMD display modes. * * @namespace Camera + * + * @hifi-interface + * @hifi-client-entity + * * @property position {Vec3} The position of the camera. You can set this value only when the camera is in independent mode. * @property orientation {Quat} The orientation of the camera. You can set this value only when the camera is in independent * mode. diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index bab15fc7b6..e74b846f02 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -40,6 +40,9 @@ class OffscreenQmlSurface; /**jsdoc * @namespace Tablet + * + * @hifi-interface + * @hifi-client-entity */ class TabletScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -176,6 +179,10 @@ Q_DECLARE_METATYPE(TabletButtonsProxyModel*); /**jsdoc * @class TabletProxy + * + * @hifi-interface + * @hifi-client-entity + * * @property {string} name - Name of this tablet. Read-only. * @property {boolean} toolbarMode - Used to transition this tablet into and out of toolbar mode. * When tablet is in toolbar mode, all its buttons will appear in a floating toolbar. @@ -410,6 +417,10 @@ Q_DECLARE_METATYPE(TabletProxy*); /**jsdoc * @class TabletButtonProxy + * + * @hifi-interface + * @hifi-client-entity + * * @property {Uuid} uuid - Uniquely identifies this button. Read-only. * @property {TabletButtonProxy.ButtonProperties} properties */ From b994776ebd98314025ecdc86fdffc91ebb42eba1 Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Mon, 30 Apr 2018 12:01:37 -0700 Subject: [PATCH 044/174] do not open help on first run --- interface/src/Application.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd4562da54..6c11286d03 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3166,9 +3166,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (firstRun.get()) { -#if !defined(Q_OS_ANDROID) - showHelp(); -#endif DependencyManager::get()->goToEntry(); sentTo = SENT_TO_ENTRY; firstRun.set(false); From 2de982a5a2751d27989cef07630d94cb62daa2c1 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 30 Apr 2018 12:04:35 -0700 Subject: [PATCH 045/174] Added script types and better script reload --- interface/src/Application.cpp | 23 +++++++++++-------- interface/src/Application.h | 2 +- interface/src/ModelPackager.cpp | 1 + interface/src/avatar/MyAvatar.cpp | 6 +---- interface/src/avatar/MyAvatar.h | 5 ---- libraries/fbx/src/FSTReader.cpp | 22 ++++++++++++++++++ libraries/fbx/src/FSTReader.h | 2 ++ .../src/model-networking/ModelCache.cpp | 19 +++++++-------- libraries/script-engine/src/ScriptEngine.cpp | 14 +++++++++++ libraries/script-engine/src/ScriptEngine.h | 12 ++++++++++ libraries/script-engine/src/ScriptEngines.cpp | 6 +++-- libraries/script-engine/src/ScriptEngines.h | 2 +- 12 files changed, 81 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38bb9295a..833224510b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1231,6 +1231,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] { getEntities()->reloadEntityScripts(); + loadAvatarScripts(getMyAvatar()->getSkeletonModel()->getFBXGeometry().scripts); }, Qt::QueuedConnection); connect(scriptEngines, &ScriptEngines::scriptLoadError, @@ -2285,10 +2286,6 @@ void Application::onAboutToQuit() { // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); - if (auto avatar = getMyAvatar()) { - auto urls = avatar->getScriptsToUnload(); - unloadAvatarScripts(urls); - } _aboutToQuit = true; @@ -4737,18 +4734,24 @@ void Application::loadAvatarScripts(const QVector& urls) { for (auto url : urls) { int index = runningScripts.indexOf(url); if (index < 0) { - scriptEngines->loadScript(url); - getMyAvatar()->addScriptToUnload(url); + auto scriptEnginePointer = scriptEngines->loadScript(url, false); + if (scriptEnginePointer) { + scriptEnginePointer->setType(ScriptEngine::Type::AVATAR); + } } } } } -void Application::unloadAvatarScripts(const QVector& urls) { - if (urls.size() > 0) { - auto scriptEngines = DependencyManager::get(); +void Application::unloadAvatarScripts() { + auto scriptEngines = DependencyManager::get(); + auto urls = scriptEngines->getRunningScripts(); + if (urls.size() > 0) { for (auto url : urls) { - scriptEngines->stopScript(url, false); + auto scriptEngine = scriptEngines->getScriptEngine(url); + if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) { + scriptEngines->stopScript(url, false); + } } } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 2e91f842a4..28c85ec855 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -291,7 +291,7 @@ public: void replaceDomainContent(const QString& url); void loadAvatarScripts(const QVector& urls); - void unloadAvatarScripts(const QVector& urls); + void unloadAvatarScripts(); signals: void svoImportRequested(const QString& url); diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index a87669bf47..72b99ce5a3 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -177,6 +177,7 @@ bool ModelPackager::zipModel() { _scriptDir = _modelFile.path() + "/" + scriptField; QDir wdir = QDir(_scriptDir); _mapping.remove(SCRIPT_FIELD); + wdir.setSorting(QDir::Name | QDir::Reversed); auto list = wdir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries); for (auto script : list) { auto sc = tempDir.relativeFilePath(scriptDir.path()) + "/" + QUrl(script).fileName(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 462dbebbbb..99fdea0449 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -123,6 +123,7 @@ MyAvatar::MyAvatar(QThread* thread) : connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) { if (success) { + qApp->unloadAvatarScripts(); auto geometry = getSkeletonModel()->getFBXGeometry(); qApp->loadAvatarScripts(geometry.scripts); } @@ -1469,7 +1470,6 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - qApp->unloadAvatarScripts(_scriptsToUnload); _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); @@ -2838,10 +2838,6 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } -void MyAvatar::addScriptToUnload(const QString& url) { - _scriptsToUnload.push_back(url); -} - void MyAvatar::setSprintMode(bool sprint) { _walkSpeedScalar = sprint ? AVATAR_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 00cb50e079..a927a1d0ba 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,9 +594,6 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; - void addScriptToUnload(const QString& url); - const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; - public slots: void increaseSize(); void decreaseSize(); @@ -907,8 +904,6 @@ private: // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; - - QVector _scriptsToUnload; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index 603f214c3e..fcbfca1e7d 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -187,6 +187,28 @@ FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) { return ENTITY_MODEL; } +QVector FSTReader::getScripts(const QUrl& url, const QVariantHash& mapping) { + + auto fstMapping = mapping.isEmpty() ? downloadMapping(url.toString()) : mapping; + QVector scriptPaths; + if (!fstMapping.value(SCRIPT_FIELD).isNull()) { + auto scripts = fstMapping.values(SCRIPT_FIELD).toVector(); + if (scripts.size() > 0) { + for (auto &script : scripts) { + QString scriptPath = script.toString(); + if (QUrl(scriptPath).isRelative()) { + if (scriptPath.at(0) == '/') { + scriptPath = scriptPath.right(scriptPath.length() - 1); + } + scriptPath = url.resolved(QUrl(scriptPath)).toString(); + } + scriptPaths.push_back(scriptPath); + } + } + } + return scriptPaths; +} + QVariantHash FSTReader::downloadMapping(const QString& url) { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(url); diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index d1204c0876..4a8574f0cf 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -50,6 +50,8 @@ public: /// Predicts the type of model by examining the mapping static ModelType predictModelType(const QVariantHash& mapping); + static QVector getScripts(const QUrl& fstUrl, const QVariantHash& mapping = QVariantHash()); + static QString getNameFromType(ModelType modelType); static FSTReader::ModelType getTypeFromName(const QString& name); static QVariantHash downloadMapping(const QString& url); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index e3f543c403..e1086bc0c9 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -83,6 +83,14 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { _textureBaseUrl = url.resolved(QUrl(".")); } + auto scripts = FSTReader::getScripts(_url, mapping); + if (scripts.size() > 0) { + mapping.remove(SCRIPT_FIELD); + for (auto &scriptPath : scripts) { + mapping.insertMulti(SCRIPT_FIELD, scriptPath); + } + } + auto animGraphVariant = mapping.value("animGraphUrl"); if (animGraphVariant.isValid()) { QUrl fstUrl(animGraphVariant.toString()); @@ -210,19 +218,12 @@ void GeometryReader::run() { throw QString("unsupported format"); } - // Store fst scripts on geometry + // Add scripts to fbxgeometry if (!_mapping.value(SCRIPT_FIELD).isNull()) { QVariantList scripts = _mapping.values(SCRIPT_FIELD); if (scripts.size() > 0) { for (auto &script : scripts) { - QString scriptUrl = script.toString(); - if (QUrl(scriptUrl).isRelative()) { - if (scriptUrl.at(0) == '/') { - scriptUrl = scriptUrl.right(scriptUrl.length() - 1); - } - scriptUrl = _url.resolved(QUrl(scriptUrl)).toString(); - } - fbxGeometry->scripts.push_back(scriptUrl); + fbxGeometry->scripts.push_back(script.toString()); } } } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index c79ffffec7..d4912fbd3d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -180,6 +180,20 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const // don't delete `ScriptEngines` until all `ScriptEngine`s are gone _scriptEngines(DependencyManager::get()) { + switch (_context) { + case Context::CLIENT_SCRIPT: + _type = Type::CLIENT; + break; + case Context::ENTITY_CLIENT_SCRIPT: + _type = Type::ENTITY_CLIENT; + break; + case Context::ENTITY_SERVER_SCRIPT: + _type = Type::ENTITY_SERVER; + break; + case Context::AGENT_SCRIPT: + _type = Type::AGENT; + } + connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { if (hasUncaughtException()) { // the engine's uncaughtException() seems to produce much better stack traces here diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7f69eee990..cf2606330f 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -99,6 +99,14 @@ public: AGENT_SCRIPT }; + enum Type { + CLIENT, + ENTITY_CLIENT, + ENTITY_SERVER, + AGENT, + AVATAR + }; + static int processLevelMaxRetries; ScriptEngine(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine")); ~ScriptEngine(); @@ -209,6 +217,9 @@ public: Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); } + void setType(Type type) { _type = type; }; + Type getType() { return _type; }; + bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget bool isRunning() const { return _isRunning; } // used by ScriptWidget @@ -293,6 +304,7 @@ protected: void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args); Context _context; + Type _type; QString _scriptContents; QString _parentURL; std::atomic _isFinished { false }; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 871705d74b..59d431fabb 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -427,11 +427,13 @@ bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { if (_scriptEnginesHash.contains(scriptURL)) { ScriptEnginePointer scriptEngine = _scriptEnginesHash[scriptURL]; if (restart) { + bool isUserLoaded = scriptEngine->isUserLoaded(); + ScriptEngine::Type type = scriptEngine->getType(); auto scriptCache = DependencyManager::get(); scriptCache->deleteScript(scriptURL); connect(scriptEngine.data(), &ScriptEngine::finished, - this, [this](QString scriptName, ScriptEnginePointer engine) { - reloadScript(scriptName); + this, [this, isUserLoaded, type](QString scriptName, ScriptEnginePointer engine) { + reloadScript(scriptName, isUserLoaded)->setType(type); }); } scriptEngine->stop(); diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index ea07ebe840..63b18c73ea 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -110,7 +110,7 @@ protected slots: protected: friend class ScriptEngine; - void reloadScript(const QString& scriptName) { loadScript(scriptName, true, false, false, true); } + ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); void onScriptEngineError(const QString& scriptFilename); From 5ab16302cac5a63f6ac3aa084850a145b43f4785 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Apr 2018 15:09:30 -0700 Subject: [PATCH 046/174] Keep CrashpadClient around --- interface/src/Crashpad.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp index e39cd42d81..27b6f4b937 100644 --- a/interface/src/Crashpad.cpp +++ b/interface/src/Crashpad.cpp @@ -11,6 +11,8 @@ #include "Crashpad.h" +#include + #include #if HAS_CRASHPAD @@ -20,7 +22,7 @@ #include #include -#include +#include #include #include @@ -28,28 +30,26 @@ #include #include +#include + using namespace crashpad; static const std::string BACKTRACE_URL { CMAKE_BACKTRACE_URL }; static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN }; -static std::wstring gIPCPipe; - extern QString qAppFileName(); std::mutex annotationMutex; crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr }; -#include + +std::unique_ptr client; LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION || pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN) { - CrashpadClient client; - if (gIPCPipe.length()) { - client.SetHandlerIPCPipe(gIPCPipe); - } - client.DumpAndCrash(pExceptionInfo); + assert(client); + client->DumpAndCrash(pExceptionInfo); } return EXCEPTION_CONTINUE_SEARCH; @@ -60,7 +60,7 @@ bool startCrashHandler() { return false; } - CrashpadClient client; + client.reset(new CrashpadClient()); std::vector arguments; std::map annotations; @@ -96,12 +96,9 @@ bool startCrashHandler() { // Enable automated uploads. database->GetSettings()->SetUploadsEnabled(true); - bool result = client.StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true); - gIPCPipe = client.GetHandlerIPCPipe(); - AddVectoredExceptionHandler(0, vectoredExceptionHandler); - return result; + return client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true); } void setCrashAnnotation(std::string name, std::string value) { From 250806252e526889820549e6ac13ce259a340ebd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Apr 2018 15:09:30 -0700 Subject: [PATCH 047/174] Don't use unique_ptr to store CrashpadClient --- interface/src/Crashpad.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp index 27b6f4b937..45f1d0778f 100644 --- a/interface/src/Crashpad.cpp +++ b/interface/src/Crashpad.cpp @@ -39,16 +39,17 @@ static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN }; extern QString qAppFileName(); +CrashpadClient* client { nullptr }; std::mutex annotationMutex; crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr }; - -std::unique_ptr client; - LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { + if (!client) { + return EXCEPTION_CONTINUE_SEARCH; + } + if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION || pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN) { - assert(client); client->DumpAndCrash(pExceptionInfo); } @@ -60,7 +61,8 @@ bool startCrashHandler() { return false; } - client.reset(new CrashpadClient()); + assert(!client); + client = new CrashpadClient(); std::vector arguments; std::map annotations; From 73cea112eefa7541a05394426f74e0652cb07efb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Apr 2018 15:49:34 -0700 Subject: [PATCH 048/174] Update FilePersistThread to use std::chrono instead of usecTimestampNow --- libraries/shared/src/shared/FileLogger.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index 4f4a9ab6dd..1e17ee9e7c 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -44,7 +44,7 @@ static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss"; static const QString LOGS_DIRECTORY = "Logs"; static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[01][0-9]-[0-3][0-9]_[0-2][0-9]\\.[0-6][0-9]\\.[0-6][0-9]"; static const QString SESSION_WILDCARD = "[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}"; -static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\.txt" }; +static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\\.txt" }; static QUuid SESSION_ID; // Max log size is 512 KB. We send log files to our crash reporter, so we want to keep this relatively @@ -52,8 +52,7 @@ static QUuid SESSION_ID; static const qint64 MAX_LOG_SIZE = 512 * 1024; // Max log files found in the log directory is 100. static const qint64 MAX_LOG_DIR_SIZE = 512 * 1024 * 100; -// Max log age is 1 hour -static const uint64_t MAX_LOG_AGE_USECS = USECS_PER_SECOND * 3600; +static const std::chrono::minutes MAX_LOG_AGE { 60 }; static FilePersistThread* _persistThreadInstance; @@ -84,23 +83,22 @@ FilePersistThread::FilePersistThread(const FileLogger& logger) : _logger(logger) if (file.exists()) { rollFileIfNecessary(file, false); } - _lastRollTime = usecTimestampNow(); + _lastRollTime = std::chrono::system_clock::now(); } void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled) { - uint64_t now = usecTimestampNow(); - if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE_USECS) { + auto now = std::chrono::system_clock::now(); + if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE) { QString newFileName = getLogRollerFilename(); if (file.copy(newFileName)) { file.open(QIODevice::WriteOnly | QIODevice::Truncate); file.close(); - qCDebug(shared) << "Rolled log file:" << newFileName; if (notifyListenersIfRolled) { emit rollingLogFile(newFileName); } - _lastRollTime = now; + _lastRollTime = std::chrono::system_clock::now(); } QDir logDir(FileUtils::standardPath(LOGS_DIRECTORY)); @@ -128,7 +126,7 @@ bool FilePersistThread::processQueueItems(const Queue& messages) { rollFileIfNecessary(file); if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { QTextStream out(&file); - foreach(const QString& message, messages) { + for (const QString& message : messages) { out << message; } } From f3fe1f3e58386363ddb2e2b5a48e5a08bd73f4c3 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 30 Apr 2018 13:51:53 -0700 Subject: [PATCH 049/174] Force crash helpers not inlined --- libraries/shared/src/CrashHelpers.cpp | 77 +++++++++++++++++++++++++++ libraries/shared/src/CrashHelpers.h | 66 +++-------------------- 2 files changed, 83 insertions(+), 60 deletions(-) create mode 100644 libraries/shared/src/CrashHelpers.cpp diff --git a/libraries/shared/src/CrashHelpers.cpp b/libraries/shared/src/CrashHelpers.cpp new file mode 100644 index 0000000000..f8ca90bc4c --- /dev/null +++ b/libraries/shared/src/CrashHelpers.cpp @@ -0,0 +1,77 @@ +// +// CrashHelpers.cpp +// libraries/shared/src +// +// Created by Clement Brisset on 4/30/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 "CrashHelpers.h" + +namespace crash { + +class B; +class A { +public: + A(B* b) : _b(b) { } + ~A(); + virtual void virtualFunction() = 0; + +private: + B* _b; +}; + +class B : public A { +public: + B() : A(this) { } + virtual void virtualFunction() override { } +}; + +A::~A() { + _b->virtualFunction(); +} + +void pureVirtualCall() { + qCDebug(shared) << "About to make a pure virtual call"; + B b; +} + +void doubleFree() { + qCDebug(shared) << "About to double delete memory"; + int* blah = new int(200); + delete blah; + delete blah; +} + +void nullDeref() { + qCDebug(shared) << "About to dereference a null pointer"; + int* p = nullptr; + *p = 1; +} + +void doAbort() { + qCDebug(shared) << "About to abort"; + abort(); +} + +void outOfBoundsVectorCrash() { + qCDebug(shared) << "std::vector out of bounds crash!"; + std::vector v; + v[0] = 42; +} + +void newFault() { + qCDebug(shared) << "About to crash inside new fault"; + + // Force crash with multiple large allocations + while (true) { + const size_t GIGABYTE = 1024 * 1024 * 1024; + new char[GIGABYTE]; + } + +} + +} diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h index 1cc6749182..ad988c8906 100644 --- a/libraries/shared/src/CrashHelpers.h +++ b/libraries/shared/src/CrashHelpers.h @@ -18,66 +18,12 @@ namespace crash { -class B; -class A { -public: - A(B* b) : _b(b) { } - ~A(); - virtual void virtualFunction() = 0; - -private: - B* _b; -}; - -class B : public A { -public: - B() : A(this) { } - virtual void virtualFunction() override { } -}; - -A::~A() { - _b->virtualFunction(); -} - -void pureVirtualCall() { - qCDebug(shared) << "About to make a pure virtual call"; - B b; -} - -void doubleFree() { - qCDebug(shared) << "About to double delete memory"; - int* blah = new int(200); - delete blah; - delete blah; -} - -void nullDeref() { - qCDebug(shared) << "About to dereference a null pointer"; - int* p = nullptr; - *p = 1; -} - -void doAbort() { - qCDebug(shared) << "About to abort"; - abort(); -} - -void outOfBoundsVectorCrash() { - qCDebug(shared) << "std::vector out of bounds crash!"; - std::vector v; - v[0] = 42; -} - -void newFault() { - qCDebug(shared) << "About to crash inside new fault"; - - // Force crash with multiple large allocations - while (true) { - const size_t GIGABYTE = 1024 * 1024 * 1024; - new char[GIGABYTE]; - } - -} +void pureVirtualCall(); +void doubleFree(); +void nullDeref(); +void doAbort(); +void outOfBoundsVectorCrash(); +void newFault(); } From 50ca09b3b421d44fa9a27177f8b7291b94a1572a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 30 Apr 2018 16:26:04 -0700 Subject: [PATCH 050/174] minor fixes --- interface/src/Application.cpp | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 833224510b..ec40ffc653 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2286,7 +2286,7 @@ void Application::onAboutToQuit() { // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); - + _aboutToQuit = true; cleanupBeforeQuit(); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d4912fbd3d..255a4832a9 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -192,6 +192,7 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const break; case Context::AGENT_SCRIPT: _type = Type::AGENT; + break; } connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { From c01fd02de2c5f427e56d75b29b57fcd4122e6d0c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 30 Apr 2018 17:23:49 -0700 Subject: [PATCH 051/174] Corrected parameter type. --- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Snapshot.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 9eb64dcb14..1af7086933 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -92,7 +92,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } -QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname) { +QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { // adding URL to snapshot QUrl currentURL = DependencyManager::get()->currentPublicAddress(); diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 20e9e8339f..86c860cfcb 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -51,7 +51,7 @@ public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); private: - static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname); + static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname); }; #endif // hifi_Snapshot_h From d5610a2f37885a0748129bc3de9dd77261ad12b0 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 30 Apr 2018 17:52:44 -0700 Subject: [PATCH 052/174] WTF... --- interface/src/ui/Snapshot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 1af7086933..d52f01223c 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -73,9 +73,9 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { return data; } -QString Snapshot::saveSnapshot(QImage image, const QString& filename) { +QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) { - QFile* snapshotFile = savedFileForSnapshot(image, false, filename); + QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname); // we don't need the snapshot file, so close it, grab its filename and delete it snapshotFile->close(); From 2ac7fcadd2c02f89b0655631d1ee3b9c4660bad5 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 1 May 2018 09:37:01 -0700 Subject: [PATCH 053/174] load scripts once on rigReady --- interface/src/avatar/MyAvatar.cpp | 6 ++++++ interface/src/avatar/MyAvatar.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 99fdea0449..85b2ece077 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -124,8 +124,14 @@ MyAvatar::MyAvatar(QThread* thread) : connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) { if (success) { qApp->unloadAvatarScripts(); + _shouldLoadScripts = true; + } + }); + connect(_skeletonModel.get(), &Model::rigReady, this, [this]() { + if (_shouldLoadScripts) { auto geometry = getSkeletonModel()->getFBXGeometry(); qApp->loadAvatarScripts(geometry.scripts); + _shouldLoadScripts = false; } }); connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a927a1d0ba..2bcbd878a9 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -904,6 +904,9 @@ private: // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; + + // load avatar scripts once when rig is ready + bool _shouldLoadScripts { false }; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); From 24ac342c6bc3cc5feeed186a2f55c4631d1b5128 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 10 Apr 2018 11:41:59 -0700 Subject: [PATCH 054/174] Add support for client texture selection --- interface/src/Application.cpp | 1 + libraries/baking/src/FBXBaker.cpp | 87 +++++++----- libraries/baking/src/FBXBaker.h | 4 +- libraries/baking/src/ModelBaker.cpp | 126 +++++++++++++++--- libraries/baking/src/ModelBaker.h | 8 +- libraries/baking/src/OBJBaker.cpp | 57 +++----- libraries/baking/src/OBJBaker.h | 5 +- libraries/baking/src/TextureBaker.cpp | 63 +++++++-- libraries/baking/src/TextureBaker.h | 14 +- libraries/fbx/src/FBXReader.cpp | 1 + libraries/fbx/src/FBXReader_Material.cpp | 4 + libraries/gpu-gl/src/gpu/gl41/GL41Backend.h | 4 +- libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 2 + .../src/gpu/gl45/GL45BackendTexture.cpp | 18 +++ libraries/gpu-gles/src/gpu/gles/GLESBackend.h | 3 +- libraries/gpu/src/gpu/Context.h | 2 + libraries/gpu/src/gpu/Texture.h | 5 + libraries/gpu/src/gpu/Texture_ktx.cpp | 77 ++++++----- libraries/ktx/src/TextureMeta.cpp | 58 ++++++++ libraries/ktx/src/TextureMeta.h | 42 ++++++ libraries/ktx/src/khronos/KHR.h | 59 ++++++++ .../src/model-networking/ModelCache.cpp | 5 +- .../src/model-networking/TextureCache.cpp | 114 +++++++++++++--- .../src/model-networking/TextureCache.h | 22 ++- libraries/networking/src/ResourceCache.cpp | 6 +- tools/oven/src/DomainBaker.cpp | 2 +- 26 files changed, 614 insertions(+), 175 deletions(-) create mode 100644 libraries/ktx/src/TextureMeta.cpp create mode 100644 libraries/ktx/src/TextureMeta.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38caca090..6756fbe255 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1296,6 +1296,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Create the main thread context, the GPU backend, and the display plugins initializeGL(); + DependencyManager::get()->setGPUContext(_gpuContext); qCDebug(interfaceapp, "Initialized Display."); // Create the rendering engine. This can be slow on some machines due to lots of // GPU pipeline creation. diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 0407c8508c..175698eeea 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -70,17 +70,66 @@ void FBXBaker::bakeSourceCopy() { return; } - // export the FBX with re-written texture references - exportScene(); - - if (shouldStop()) { - return; - } - // check if we're already done with textures (in case we had none to re-write) checkIfTexturesFinished(); } +void FBXBaker::embedTextureMetaData() { + std::vector embeddedTextureNodes; + + for (FBXNode& rootChild : _rootNode.children) { + if (rootChild.name == "Objects") { + qlonglong maxId = 0; + for (auto &child : rootChild.children) { + if (child.properties.length() == 3) { + maxId = std::max(maxId, child.properties[0].toLongLong()); + } + } + + for (auto& object : rootChild.children) { + if (object.name == "Texture") { + QVariant relativeFilename; + for (auto& child : object.children) { + if (child.name == "RelativeFilename") { + relativeFilename = child.properties[0]; + break; + } + } + + if (relativeFilename.isNull() || !relativeFilename.toString().endsWith(BAKED_META_TEXTURE_SUFFIX)) { + continue; + } + + FBXNode videoNode; + videoNode.name = "Video"; + videoNode.properties.append(++maxId); + videoNode.properties.append(object.properties[1]); + videoNode.properties.append("Clip"); + + QString bakedTextureFilePath { + _bakedOutputDir + "/" + relativeFilename.toString() + }; + qDebug() << "Location of texture: " << bakedTextureFilePath; + + QFile textureFile { bakedTextureFilePath }; + if (!textureFile.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open: " << bakedTextureFilePath; + continue; + } + + videoNode.children.append({ "RelativeFilename", { relativeFilename }, { } }); + videoNode.children.append({ "Content", { textureFile.readAll() }, { } }); + + rootChild.children.append(videoNode); + + textureFile.close(); + } + } + } + } + +} + void FBXBaker::setupOutputFolder() { // make sure there isn't already an output directory using the same name if (QDir(_bakedOutputDir).exists()) { @@ -352,27 +401,3 @@ void FBXBaker::rewriteAndBakeSceneTextures() { } } } - -void FBXBaker::exportScene() { - // save the relative path to this FBX inside our passed output folder - auto fileName = _modelURL.fileName(); - auto baseName = fileName.left(fileName.lastIndexOf('.')); - auto bakedFilename = baseName + BAKED_FBX_EXTENSION; - - _bakedModelFilePath = _bakedOutputDir + "/" + bakedFilename; - - auto fbxData = FBXWriter::encodeFBX(_rootNode); - - QFile bakedFile(_bakedModelFilePath); - - if (!bakedFile.open(QIODevice::WriteOnly)) { - handleError("Error opening " + _bakedModelFilePath + " for writing"); - return; - } - - bakedFile.write(fbxData); - - _outputFiles.push_back(_bakedModelFilePath); - - qCDebug(model_baking) << "Exported" << _modelURL << "with re-written paths to" << _bakedModelFilePath; -} diff --git a/libraries/baking/src/FBXBaker.h b/libraries/baking/src/FBXBaker.h index 2888a60f73..58a7bffa18 100644 --- a/libraries/baking/src/FBXBaker.h +++ b/libraries/baking/src/FBXBaker.h @@ -26,8 +26,6 @@ #include -static const QString BAKED_FBX_EXTENSION = ".baked.fbx"; - using TextureBakerThreadGetter = std::function; class FBXBaker : public ModelBaker { @@ -51,11 +49,11 @@ private: void loadSourceFBX(); void importScene(); + void embedTextureMetaData(); void rewriteAndBakeSceneModels(); void rewriteAndBakeSceneTextures(); void exportScene(); - FBXNode _rootNode; FBXGeometry* _geometry; QHash _textureNameMatchCount; QHash _remappedTexturePaths; diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index 16a0c89c7f..020a0dbfc2 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -248,7 +248,7 @@ QString ModelBaker::compressTexture(QString modelTextureFileName, image::Texture QFileInfo modelTextureFileInfo{ modelTextureFileName.replace("\\", "/") }; - if (modelTextureFileInfo.suffix() == BAKED_TEXTURE_EXT.mid(1)) { + if (modelTextureFileInfo.suffix() == BAKED_TEXTURE_KTX_EXT.mid(1)) { // re-baking a model that already references baked textures // this is an error - return from here handleError("Cannot re-bake a file that already references compressed textures"); @@ -273,31 +273,31 @@ QString ModelBaker::compressTexture(QString modelTextureFileName, image::Texture } auto urlToTexture = getTextureURL(modelTextureFileInfo, modelTextureFileName, !textureContent.isNull()); - QString bakedTextureFileName; + QString baseTextureFileName; if (_remappedTexturePaths.contains(urlToTexture)) { - bakedTextureFileName = _remappedTexturePaths[urlToTexture]; + baseTextureFileName = _remappedTexturePaths[urlToTexture]; } else { // construct the new baked texture file name and file path // ensuring that the baked texture will have a unique name // even if there was another texture with the same name at a different path - bakedTextureFileName = createBakedTextureFileName(modelTextureFileInfo); - _remappedTexturePaths[urlToTexture] = bakedTextureFileName; + baseTextureFileName = createBaseTextureFileName(modelTextureFileInfo); + _remappedTexturePaths[urlToTexture] = baseTextureFileName; } qCDebug(model_baking).noquote() << "Re-mapping" << modelTextureFileName - << "to" << bakedTextureFileName; + << "to" << baseTextureFileName; - QString bakedTextureFilePath{ - _bakedOutputDir + "/" + bakedTextureFileName + QString bakedTextureFilePath { + _bakedOutputDir + "/" + baseTextureFileName + BAKED_META_TEXTURE_SUFFIX }; - textureChild = bakedTextureFileName; + textureChild = baseTextureFileName + BAKED_META_TEXTURE_SUFFIX; if (!_bakingTextures.contains(urlToTexture)) { _outputFiles.push_back(bakedTextureFilePath); // bake this texture asynchronously - bakeTexture(urlToTexture, textureType, _bakedOutputDir, bakedTextureFileName, textureContent); + bakeTexture(urlToTexture, textureType, _bakedOutputDir, baseTextureFileName, textureContent); } } @@ -309,7 +309,7 @@ void ModelBaker::bakeTexture(const QUrl& textureURL, image::TextureUsage::Type t // start a bake for this texture and add it to our list to keep track of QSharedPointer bakingTexture{ - new TextureBaker(textureURL, textureType, outputDir, bakedFilename, textureContent), + new TextureBaker(textureURL, textureType, outputDir, "../", bakedFilename, textureContent), &TextureBaker::deleteLater }; @@ -484,30 +484,30 @@ void ModelBaker::checkIfTexturesFinished() { } else { qCDebug(model_baking) << "Finished baking, emitting finished" << _modelURL; + texturesFinished(); + setIsFinished(true); } } } -QString ModelBaker::createBakedTextureFileName(const QFileInfo& textureFileInfo) { +QString ModelBaker::createBaseTextureFileName(const QFileInfo& textureFileInfo) { // first make sure we have a unique base name for this texture // in case another texture referenced by this model has the same base name auto& nameMatches = _textureNameMatchCount[textureFileInfo.baseName()]; - QString bakedTextureFileName{ textureFileInfo.completeBaseName() }; + QString baseTextureFileName{ textureFileInfo.completeBaseName() }; if (nameMatches > 0) { // there are already nameMatches texture with this name // append - and that number to our baked texture file name so that it is unique - bakedTextureFileName += "-" + QString::number(nameMatches); + baseTextureFileName += "-" + QString::number(nameMatches); } - bakedTextureFileName += BAKED_TEXTURE_EXT; - // increment the number of name matches ++nameMatches; - return bakedTextureFileName; + return baseTextureFileName; } void ModelBaker::setWasAborted(bool wasAborted) { @@ -519,3 +519,95 @@ void ModelBaker::setWasAborted(bool wasAborted) { } } } + +void ModelBaker::texturesFinished() { + embedTextureMetaData(); + exportScene(); +} + +void ModelBaker::embedTextureMetaData() { + std::vector embeddedTextureNodes; + + for (FBXNode& rootChild : _rootNode.children) { + if (rootChild.name == "Objects") { + qlonglong maxId = 0; + for (auto &child : rootChild.children) { + if (child.properties.length() == 3) { + maxId = std::max(maxId, child.properties[0].toLongLong()); + } + } + + qDebug() << "Max id found was: " << maxId; + + for (auto& object : rootChild.children) { + if (object.name == "Texture") { + QVariant relativeFilename; + for (auto& child : object.children) { + if (child.name == "RelativeFilename") { + relativeFilename = child.properties[0]; + break; + } + } + + if (relativeFilename.isNull() + || !relativeFilename.toString().endsWith(BAKED_META_TEXTURE_SUFFIX)) { + continue; + } + if (object.properties.length() < 2) { + qWarning() << "Found texture with unexpected number of properties: " << object.name; + continue; + } + + FBXNode videoNode; + videoNode.name = "Video"; + videoNode.properties.append(++maxId); + videoNode.properties.append(object.properties[1]); + videoNode.properties.append("Clip"); + + QString bakedTextureFilePath { + _bakedOutputDir + "/" + relativeFilename.toString() + }; + qDebug() << "Location of texture: " << bakedTextureFilePath; + + QFile textureFile { bakedTextureFilePath }; + if (!textureFile.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open: " << bakedTextureFilePath; + continue; + } + + videoNode.children.append({ "RelativeFilename", { relativeFilename }, { } }); + videoNode.children.append({ "Content", { textureFile.readAll() }, { } }); + + rootChild.children.append(videoNode); + + textureFile.close(); + } + } + } + } + +} + +void ModelBaker::exportScene() { + // save the relative path to this FBX inside our passed output folder + auto fileName = _modelURL.fileName(); + auto baseName = fileName.left(fileName.lastIndexOf('.')); + auto bakedFilename = baseName + BAKED_FBX_EXTENSION; + + _bakedModelFilePath = _bakedOutputDir + "/" + bakedFilename; + + auto fbxData = FBXWriter::encodeFBX(_rootNode); + + QFile bakedFile(_bakedModelFilePath); + + if (!bakedFile.open(QIODevice::WriteOnly)) { + handleError("Error opening " + _bakedModelFilePath + " for writing"); + return; + } + + bakedFile.write(fbxData); + + _outputFiles.push_back(_bakedModelFilePath); + + qCDebug(model_baking) << "Exported" << _modelURL << "with re-written paths to" << _bakedModelFilePath; +} diff --git a/libraries/baking/src/ModelBaker.h b/libraries/baking/src/ModelBaker.h index 6fd529af92..1fd77ab761 100644 --- a/libraries/baking/src/ModelBaker.h +++ b/libraries/baking/src/ModelBaker.h @@ -29,6 +29,8 @@ using TextureBakerThreadGetter = std::function; using GetMaterialIDCallback = std::function ; +static const QString BAKED_FBX_EXTENSION = ".baked.fbx"; + class ModelBaker : public Baker { Q_OBJECT @@ -49,7 +51,11 @@ public slots: protected: void checkIfTexturesFinished(); + void texturesFinished(); + void embedTextureMetaData(); + void exportScene(); + FBXNode _rootNode; QHash _textureContentMap; QUrl _modelURL; QString _bakedOutputDir; @@ -63,7 +69,7 @@ private slots: void handleAbortedTexture(); private: - QString createBakedTextureFileName(const QFileInfo & textureFileInfo); + QString createBaseTextureFileName(const QFileInfo & textureFileInfo); QUrl getTextureURL(const QFileInfo& textureFileInfo, QString relativeFileName, bool isEmbedded = false); void bakeTexture(const QUrl & textureURL, image::TextureUsage::Type textureType, const QDir & outputDir, const QString & bakedFilename, const QByteArray & textureContent); diff --git a/libraries/baking/src/OBJBaker.cpp b/libraries/baking/src/OBJBaker.cpp index 85771ff2e3..1fe53f26eb 100644 --- a/libraries/baking/src/OBJBaker.cpp +++ b/libraries/baking/src/OBJBaker.cpp @@ -147,31 +147,7 @@ void OBJBaker::bakeOBJ() { auto geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL); // Write OBJ Data as FBX tree nodes - FBXNode rootNode; - createFBXNodeTree(rootNode, *geometry); - - // Serialize the resultant FBX tree - auto encodedFBX = FBXWriter::encodeFBX(rootNode); - - // Export as baked FBX - auto fileName = _modelURL.fileName(); - auto baseName = fileName.left(fileName.lastIndexOf('.')); - auto bakedFilename = baseName + ".baked.fbx"; - - _bakedModelFilePath = _bakedOutputDir + "/" + bakedFilename; - - QFile bakedFile; - bakedFile.setFileName(_bakedModelFilePath); - if (!bakedFile.open(QIODevice::WriteOnly)) { - handleError("Error opening " + _bakedModelFilePath + " for writing"); - return; - } - - bakedFile.write(encodedFBX); - - // Export successful - _outputFiles.push_back(_bakedModelFilePath); - qCDebug(model_baking) << "Exported" << _modelURL << "to" << _bakedModelFilePath; + createFBXNodeTree(_rootNode, *geometry); checkIfTexturesFinished(); } @@ -203,15 +179,17 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { globalSettingsNode.children = { properties70Node }; // Generating Object node - _objectNode.name = OBJECTS_NODE_NAME; + FBXNode objectNode; + objectNode.name = OBJECTS_NODE_NAME; // Generating Object node's child - Geometry node FBXNode geometryNode; geometryNode.name = GEOMETRY_NODE_NAME; + NodeID geometryID; { - _geometryID = nextNodeID(); + geometryID = nextNodeID(); geometryNode.properties = { - _geometryID, + geometryID, GEOMETRY_NODE_NAME, MESH }; @@ -226,12 +204,13 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { // Generating Object node's child - Model node FBXNode modelNode; modelNode.name = MODEL_NODE_NAME; + NodeID modelID; { - _modelID = nextNodeID(); - modelNode.properties = { _modelID, MODEL_NODE_NAME, MESH }; + modelID = nextNodeID(); + modelNode.properties = { modelID, MODEL_NODE_NAME, MESH }; } - _objectNode.children = { geometryNode, modelNode }; + objectNode.children = { geometryNode, modelNode }; // Generating Objects node's child - Material node auto& meshParts = geometry.meshes[0].parts; @@ -247,7 +226,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { setMaterialNodeProperties(materialNode, meshPart.materialID, geometry); } - _objectNode.children.append(materialNode); + objectNode.children.append(materialNode); } // Generating Texture Node @@ -257,13 +236,13 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { QString material = meshParts[i].materialID; FBXMaterial currentMaterial = geometry.materials[material]; if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) { - _textureID = nextNodeID(); - _mapTextureMaterial.emplace_back(_textureID, i); + auto textureID = nextNodeID(); + _mapTextureMaterial.emplace_back(textureID, i); FBXNode textureNode; { textureNode.name = TEXTURE_NODE_NAME; - textureNode.properties = { _textureID }; + textureNode.properties = { textureID, "texture" + QString::number(textureID) }; } // Texture node child - TextureName node @@ -295,7 +274,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { textureNode.children = { textureNameNode, relativeFilenameNode }; - _objectNode.children.append(textureNode); + objectNode.children.append(textureNode); } } @@ -306,14 +285,14 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { // connect Geometry to Model FBXNode cNode; cNode.name = C_NODE_NAME; - cNode.properties = { CONNECTIONS_NODE_PROPERTY, _geometryID, _modelID }; + cNode.properties = { CONNECTIONS_NODE_PROPERTY, geometryID, modelID }; connectionsNode.children = { cNode }; // connect all materials to model for (auto& materialID : _materialIDs) { FBXNode cNode; cNode.name = C_NODE_NAME; - cNode.properties = { CONNECTIONS_NODE_PROPERTY, materialID, _modelID }; + cNode.properties = { CONNECTIONS_NODE_PROPERTY, materialID, modelID }; connectionsNode.children.append(cNode); } @@ -341,7 +320,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) { } // Make all generated nodes children of rootNode - rootNode.children = { globalSettingsNode, _objectNode, connectionsNode }; + rootNode.children = { globalSettingsNode, objectNode, connectionsNode }; } // Set properties for material nodes diff --git a/libraries/baking/src/OBJBaker.h b/libraries/baking/src/OBJBaker.h index e888c7b1d8..8e49692d35 100644 --- a/libraries/baking/src/OBJBaker.h +++ b/libraries/baking/src/OBJBaker.h @@ -43,12 +43,9 @@ private: void setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry); NodeID nextNodeID() { return _nodeID++; } + NodeID _nodeID { 0 }; - NodeID _geometryID; - NodeID _modelID; std::vector _materialIDs; - NodeID _textureID; std::vector> _mapTextureMaterial; - FBXNode _objectNode; }; #endif // hifi_OBJBaker_h diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index b6edd07965..7a5dc85a61 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -18,26 +18,30 @@ #include #include #include +#include #include "ModelBakingLoggingCategory.h" #include "TextureBaker.h" -const QString BAKED_TEXTURE_EXT = ".ktx"; +const QString BAKED_TEXTURE_KTX_EXT = ".ktx"; +const QString BAKED_TEXTURE_BCN_SUFFIX = "_bcn.ktx"; +const QString BAKED_META_TEXTURE_SUFFIX = ".texmeta.json"; TextureBaker::TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, - const QDir& outputDirectory, const QString& bakedFilename, - const QByteArray& textureContent) : + const QDir& outputDirectory, const QString& metaTexturePathPrefix, + const QString& baseFilename, const QByteArray& textureContent) : _textureURL(textureURL), _originalTexture(textureContent), _textureType(textureType), + _baseFilename(baseFilename), _outputDirectory(outputDirectory), - _bakedTextureFileName(bakedFilename) + _metaTexturePathPrefix(metaTexturePathPrefix) { - if (bakedFilename.isEmpty()) { + if (baseFilename.isEmpty()) { // figure out the baked texture filename auto originalFilename = textureURL.fileName(); - _bakedTextureFileName = originalFilename.left(originalFilename.lastIndexOf('.')) + BAKED_TEXTURE_EXT; + _baseFilename = originalFilename.left(originalFilename.lastIndexOf('.')); } } @@ -118,6 +122,19 @@ void TextureBaker::processTexture() { auto hashData = QCryptographicHash::hash(_originalTexture, QCryptographicHash::Md5); std::string hash = hashData.toHex().toStdString(); + TextureMeta meta; + + { + auto filePath = _outputDirectory.absoluteFilePath(_textureURL.fileName()); + QFile file { filePath }; + if (!file.open(QIODevice::WriteOnly) || file.write(_originalTexture) == -1) { + handleError("Could not write meta texture for " + _textureURL.toString()); + return; + } + _outputFiles.push_back(filePath); + meta.original =_metaTexturePathPrefix +_textureURL.fileName(); + } + // IMPORTANT: _originalTexture is empty past this point auto processedTexture = image::processImage(std::move(_originalTexture), _textureURL.toString().toStdString(), ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, _abortProcessing); @@ -142,15 +159,37 @@ void TextureBaker::processTexture() { const char* data = reinterpret_cast(memKTX->_storage->data()); const size_t length = memKTX->_storage->size(); + const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat()); + if (name == nullptr) { + handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString()); + return; + } + + qDebug() << "Found type: " << name; // attempt to write the baked texture to the destination file path - auto filePath = _outputDirectory.absoluteFilePath(_bakedTextureFileName); - QFile bakedTextureFile { filePath }; - - if (!bakedTextureFile.open(QIODevice::WriteOnly) || bakedTextureFile.write(data, length) == -1) { - handleError("Could not write baked texture for " + _textureURL.toString()); - } else { + { + auto fileName = _baseFilename + BAKED_TEXTURE_BCN_SUFFIX; + auto filePath = _outputDirectory.absoluteFilePath(fileName); + QFile bakedTextureFile { filePath }; + if (!bakedTextureFile.open(QIODevice::WriteOnly) || bakedTextureFile.write(data, length) == -1) { + handleError("Could not write baked texture for " + _textureURL.toString()); + return; + } _outputFiles.push_back(filePath); + meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName; + } + + + { + auto data = meta.serialize(); + _metaTextureFileName = _outputDirectory.absoluteFilePath(_baseFilename + BAKED_META_TEXTURE_SUFFIX); + QFile file { _metaTextureFileName }; + if (!file.open(QIODevice::WriteOnly) || file.write(data) == -1) { + handleError("Could not write meta texture for " + _textureURL.toString()); + } else { + _outputFiles.push_back(_metaTextureFileName); + } } qCDebug(model_baking) << "Baked texture" << _textureURL; diff --git a/libraries/baking/src/TextureBaker.h b/libraries/baking/src/TextureBaker.h index 90ecfe52f7..93b01080cd 100644 --- a/libraries/baking/src/TextureBaker.h +++ b/libraries/baking/src/TextureBaker.h @@ -21,22 +21,22 @@ #include "Baker.h" -extern const QString BAKED_TEXTURE_EXT; +extern const QString BAKED_TEXTURE_KTX_EXT; +extern const QString BAKED_META_TEXTURE_SUFFIX; class TextureBaker : public Baker { Q_OBJECT public: TextureBaker(const QUrl& textureURL, image::TextureUsage::Type textureType, - const QDir& outputDirectory, const QString& bakedFilename = QString(), - const QByteArray& textureContent = QByteArray()); + const QDir& outputDirectory, const QString& metaTexturePathPrefix = "", + const QString& baseFilename = QString(), const QByteArray& textureContent = QByteArray()); const QByteArray& getOriginalTexture() const { return _originalTexture; } QUrl getTextureURL() const { return _textureURL; } - QString getDestinationFilePath() const { return _outputDirectory.absoluteFilePath(_bakedTextureFileName); } - QString getBakedTextureFileName() const { return _bakedTextureFileName; } + QString getMetaTextureFileName() const { return _metaTextureFileName; } virtual void setWasAborted(bool wasAborted) override; @@ -58,8 +58,10 @@ private: QByteArray _originalTexture; image::TextureUsage::Type _textureType; + QString _baseFilename; QDir _outputDirectory; - QString _bakedTextureFileName; + QString _metaTextureFileName; + QString _metaTexturePathPrefix; std::atomic _abortProcessing { false }; }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1e59646795..1f237edfb0 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1101,6 +1101,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } if (!content.isEmpty()) { _textureContent.insert(filepath, content); + qDebug() << "Adding content: " << filepath << content.length(); } } else if (object.name == "Material") { FBXMaterial material; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 4aa3044934..88dc7f599d 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -85,12 +85,16 @@ FBXTexture FBXReader::getTexture(const QString& textureID) { FBXTexture texture; const QByteArray& filepath = _textureFilepaths.value(textureID); texture.content = _textureContent.value(filepath); + qDebug() << "Getting texture: " << textureID << filepath << texture.content.length(); if (texture.content.isEmpty()) { // the content is not inlined + qDebug() << "Texture is not inlined"; texture.filename = _textureFilenames.value(textureID); } else { // use supplied filepath for inlined content + qDebug() << "Texture is inlined"; texture.filename = filepath; } + qDebug() << "Path: " << texture.filename; texture.id = textureID; texture.name = _textureNames.value(textureID); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 9479321747..f3b452b1f9 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -52,6 +52,8 @@ public: static const std::string GL41_VERSION; const std::string& getVersion() const override { return GL41_VERSION; } + bool supportedTextureFormat(const gpu::Element& format) override; + class GL41Texture : public GLTexture { using Parent = GLTexture; friend class GL41Backend; @@ -173,8 +175,6 @@ protected: void makeProgramBindings(ShaderObject& shaderObject) override; int makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override; - static bool supportedTextureFormat(const gpu::Element& format); - }; } } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index c23a83eaf9..616b6d1075 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -54,6 +54,8 @@ public: static const std::string GL45_VERSION; const std::string& getVersion() const override { return GL45_VERSION; } + bool supportedTextureFormat(const gpu::Element& format) override; + class GL45Texture : public GLTexture { using Parent = GLTexture; friend class GL45Backend; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 4d5ffefa67..6b3c99ccc3 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -32,6 +32,24 @@ using namespace gpu::gl45; #define FORCE_STRICT_TEXTURE 0 #define ENABLE_SPARSE_TEXTURE 0 +bool GL45Backend::supportedTextureFormat(const gpu::Element& format) { + switch (format.getSemantic()) { + case gpu::Semantic::COMPRESSED_ETC2_RGB: + case gpu::Semantic::COMPRESSED_ETC2_SRGB: + case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: + case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA: + case gpu::Semantic::COMPRESSED_ETC2_RGBA: + case gpu::Semantic::COMPRESSED_ETC2_SRGBA: + case gpu::Semantic::COMPRESSED_EAC_RED: + case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED: + case gpu::Semantic::COMPRESSED_EAC_XY: + case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED: + return false; + default: + return true; + } +} + GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) { if (!texturePointer) { return nullptr; diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackend.h b/libraries/gpu-gles/src/gpu/gles/GLESBackend.h index 38e28e630a..47a123718a 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackend.h +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackend.h @@ -32,7 +32,6 @@ public: static const GLint RESOURCE_TRANSFER_EXTRA_TEX_UNIT { 33 }; static const GLint RESOURCE_BUFFER_TEXBUF_TEX_UNIT { 34 }; static const GLint RESOURCE_BUFFER_SLOT0_TEX_UNIT { 35 }; - static bool supportedTextureFormat(const gpu::Element& format); explicit GLESBackend(bool syncCache) : Parent(syncCache) {} GLESBackend() : Parent() {} virtual ~GLESBackend() { @@ -40,6 +39,8 @@ public: // which is pure virtual from GLBackend's dtor. resetStages(); } + + bool supportedTextureFormat(const gpu::Element& format) override; static const std::string GLES_VERSION; const std::string& getVersion() const override { return GLES_VERSION; } diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index eda8fee596..8c5a4d493e 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -64,6 +64,8 @@ public: virtual void recycle() const = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; + virtual bool supportedTextureFormat(const gpu::Element& format) = 0; + // Shared header between C++ and GLSL #include "TransformCamera_shared.slh" diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 4d82aba595..09b2bc9475 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -37,6 +37,10 @@ namespace ktx { using KeyValues = std::list; } +namespace khronos { namespace gl { namespace texture { + enum class InternalFormat: uint32_t; +}}} + namespace gpu { @@ -565,6 +569,7 @@ public: static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header); static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat); + static bool getCompressedFormat(khronos::gl::texture::InternalFormat format, Element& elFormat); protected: const TextureUsageType _usageType; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 5e354c0a5c..0822af3cfb 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -619,6 +619,47 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat return true; } +bool Texture::getCompressedFormat(ktx::GLInternalFormat format, Element& elFormat) { + if (format == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) { + elFormat = Format::COLOR_COMPRESSED_BCX_SRGB; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { + elFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_MASK; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { + elFormat = Format::COLOR_COMPRESSED_BCX_SRGBA; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) { + elFormat = Format::COLOR_COMPRESSED_BCX_RED; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) { + elFormat = Format::COLOR_COMPRESSED_BCX_XY; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { + elFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) { + elFormat = Format::COLOR_COMPRESSED_BCX_HDR_RGB; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RGB8_ETC2) { + elFormat = Format::COLOR_COMPRESSED_ETC2_RGB; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SRGB8_ETC2) { + elFormat = Format::COLOR_COMPRESSED_ETC2_SRGB; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) { + elFormat = Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) { + elFormat = Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC) { + elFormat = Format::COLOR_COMPRESSED_ETC2_RGBA; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) { + elFormat = Format::COLOR_COMPRESSED_ETC2_SRGBA; + } else if (format == ktx::GLInternalFormat::COMPRESSED_R11_EAC) { + elFormat = Format::COLOR_COMPRESSED_EAC_RED; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SIGNED_R11_EAC) { + elFormat = Format::COLOR_COMPRESSED_EAC_RED_SIGNED; + } else if (format == ktx::GLInternalFormat::COMPRESSED_RG11_EAC) { + elFormat = Format::COLOR_COMPRESSED_EAC_XY; + } else if (format == ktx::GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC) { + elFormat = Format::COLOR_COMPRESSED_EAC_XY_SIGNED; + } else { + return false; + } + return true; +} + bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat) { if (header.getGLFormat() == ktx::GLFormat::BGRA && header.getGLType() == ktx::GLType::UNSIGNED_BYTE && header.getTypeSize() == 1) { if (header.getGLInternaFormat() == ktx::GLInternalFormat::RGBA8) { @@ -661,41 +702,7 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E mipFormat = Format::COLOR_RGB9E5; texelFormat = Format::COLOR_RGB9E5; } else if (header.isCompressed()) { - if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) { - texelFormat = Format::COLOR_COMPRESSED_BCX_SRGB; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { - texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_MASK; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { - texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) { - texelFormat = Format::COLOR_COMPRESSED_BCX_RED; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) { - texelFormat = Format::COLOR_COMPRESSED_BCX_XY; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { - texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) { - texelFormat = Format::COLOR_COMPRESSED_BCX_HDR_RGB; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB8_ETC2) { - texelFormat = Format::COLOR_COMPRESSED_ETC2_RGB; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_ETC2) { - texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGB; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) { - texelFormat = Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) { - texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC) { - texelFormat = Format::COLOR_COMPRESSED_ETC2_RGBA; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) { - texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGBA; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_R11_EAC) { - texelFormat = Format::COLOR_COMPRESSED_EAC_RED; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SIGNED_R11_EAC) { - texelFormat = Format::COLOR_COMPRESSED_EAC_RED_SIGNED; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG11_EAC) { - texelFormat = Format::COLOR_COMPRESSED_EAC_XY; - } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC) { - texelFormat = Format::COLOR_COMPRESSED_EAC_XY_SIGNED; - } else { + if (!getCompressedFormat(header.getGLInternaFormat(), texelFormat)) { return false; } mipFormat = texelFormat; diff --git a/libraries/ktx/src/TextureMeta.cpp b/libraries/ktx/src/TextureMeta.cpp new file mode 100644 index 0000000000..88235d8a4b --- /dev/null +++ b/libraries/ktx/src/TextureMeta.cpp @@ -0,0 +1,58 @@ +// +// TextureMeta.cpp +// libraries/shared/src +// +// Created by Ryan Huffman on 04/10/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 "TextureMeta.h" + +#include +#include + +const QString TEXTURE_META_EXTENSION = ".texmeta.json"; + +bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) { + QJsonParseError error; + auto doc = QJsonDocument::fromJson(data, &error); + if (!doc.isObject()) { + return false; + } + + auto root = doc.object(); + if (root.contains("original")) { + meta->original = root["original"].toString(); + } + if (root.contains("compressed")) { + auto compressed = root["compressed"].toObject(); + for (auto it = compressed.constBegin(); it != compressed.constEnd(); it++) { + khronos::gl::texture::InternalFormat format; + auto formatName = it.key().toLatin1(); + if (khronos::gl::texture::fromString(formatName.constData(), &format)) { + meta->availableTextureTypes[format] = it.value().toString(); + } + } + } + + return true; +} + +QByteArray TextureMeta::serialize() { + QJsonDocument doc; + QJsonObject root; + QJsonObject compressed; + + for (auto kv : availableTextureTypes) { + const char* name = khronos::gl::texture::toString(kv.first); + compressed[name] = kv.second.toString(); + } + root["original"] = original.toString(); + root["compressed"] = compressed; + doc.setObject(root); + + return doc.toJson(); +} diff --git a/libraries/ktx/src/TextureMeta.h b/libraries/ktx/src/TextureMeta.h new file mode 100644 index 0000000000..6582c29e70 --- /dev/null +++ b/libraries/ktx/src/TextureMeta.h @@ -0,0 +1,42 @@ +// +// TextureMeta.h +// libraries/shared/src +// +// Created by Ryan Huffman on 04/10/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 +// + +#ifndef hifi_TextureMeta_h +#define hifi_TextureMeta_h + +#include +#include +#include + +#include "khronos/KHR.h" + +extern const QString TEXTURE_META_EXTENSION; + +namespace std { + template<> struct hash { + using enum_type = std::underlying_type::type; + typedef std::size_t result_type; + result_type operator()(khronos::gl::texture::InternalFormat const& v) const noexcept { + return std::hash()(static_cast(v)); + } + }; +} + +struct TextureMeta { + static bool deserialize(const QByteArray& data, TextureMeta* meta); + QByteArray serialize(); + + QUrl original; + std::unordered_map availableTextureTypes; +}; + + +#endif // hifi_TextureMeta_h diff --git a/libraries/ktx/src/khronos/KHR.h b/libraries/ktx/src/khronos/KHR.h index 4ee893e4fc..617e40ce06 100644 --- a/libraries/ktx/src/khronos/KHR.h +++ b/libraries/ktx/src/khronos/KHR.h @@ -10,6 +10,8 @@ #ifndef khronos_khr_hpp #define khronos_khr_hpp +#include + namespace khronos { namespace gl { @@ -209,6 +211,63 @@ namespace khronos { COMPRESSED_SIGNED_RG11_EAC = 0x9273, }; + static std::unordered_map nameToFormat { + { "COMPRESSED_RED", InternalFormat::COMPRESSED_RED }, + { "COMPRESSED_RG", InternalFormat::COMPRESSED_RG }, + { "COMPRESSED_RGB", InternalFormat::COMPRESSED_RGB }, + { "COMPRESSED_RGBA", InternalFormat::COMPRESSED_RGBA }, + + { "COMPRESSED_SRGB", InternalFormat::COMPRESSED_SRGB }, + { "COMPRESSED_SRGB_ALPHA", InternalFormat::COMPRESSED_SRGB_ALPHA }, + + { "COMPRESSED_ETC1_RGB8_OES", InternalFormat::COMPRESSED_ETC1_RGB8_OES }, + + { "COMPRESSED_SRGB_S3TC_DXT1_EXT", InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT }, + { "COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT", InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT }, + { "COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT", InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT }, + { "COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT", InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT }, + + { "COMPRESSED_RED_RGTC1", InternalFormat::COMPRESSED_RED_RGTC1 }, + { "COMPRESSED_SIGNED_RED_RGTC1", InternalFormat::COMPRESSED_SIGNED_RED_RGTC1 }, + { "COMPRESSED_RG_RGTC2", InternalFormat::COMPRESSED_RG_RGTC2 }, + { "COMPRESSED_SIGNED_RG_RGTC2", InternalFormat::COMPRESSED_SIGNED_RG_RGTC2 }, + + { "COMPRESSED_RGBA_BPTC_UNORM", InternalFormat::COMPRESSED_RGBA_BPTC_UNORM }, + { "COMPRESSED_SRGB_ALPHA_BPTC_UNORM", InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM }, + { "COMPRESSED_RGB_BPTC_SIGNED_FLOAT", InternalFormat::COMPRESSED_RGB_BPTC_SIGNED_FLOAT }, + { "COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT", InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT }, + + { "COMPRESSED_RGB8_ETC2", InternalFormat::COMPRESSED_RGB8_ETC2 }, + { "COMPRESSED_SRGB8_ETC2", InternalFormat::COMPRESSED_SRGB8_ETC2 }, + { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 }, + { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 }, + { "COMPRESSED_RGBA8_ETC2_EAC", InternalFormat::COMPRESSED_RGBA8_ETC2_EAC }, + { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC }, + + { "COMPRESSED_R11_EAC", InternalFormat::COMPRESSED_R11_EAC }, + { "COMPRESSED_SIGNED_R11_EAC", InternalFormat::COMPRESSED_SIGNED_R11_EAC }, + { "COMPRESSED_RG11_EAC", InternalFormat::COMPRESSED_RG11_EAC }, + { "COMPRESSED_SIGNED_RG11_EAC", InternalFormat::COMPRESSED_SIGNED_RG11_EAC } + }; + + inline const char* toString(InternalFormat format) { + for (auto& pair : nameToFormat) { + if (pair.second == format) { + return pair.first.data(); + } + } + return nullptr; + } + + inline bool fromString(const char* name, InternalFormat* format) { + auto it = nameToFormat.find(name); + if (it == nameToFormat.end()) { + return false; + } + *format = it->second; + return true; + } + inline uint8_t evalUncompressedBlockBitSize(InternalFormat format) { switch (format) { case InternalFormat::R8: diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index f17cdbb7e8..6756941520 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -517,10 +517,11 @@ QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& textu // Inlined file: cache under the fbx file to avoid namespace clashes // NOTE: We cannot resolve the path because filename may be an absolute path assert(texture.filename.size() > 0); + auto baseUrlStripped = baseUrl.toDisplayString(QUrl::RemoveFragment | QUrl::RemoveQuery | QUrl::RemoveUserInfo); if (texture.filename.at(0) == '/') { - return baseUrl.toString() + texture.filename; + return baseUrlStripped + texture.filename; } else { - return baseUrl.toString() + '/' + texture.filename; + return baseUrlStripped + '/' + texture.filename; } } } diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 04696cea1a..54b654c56b 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -48,6 +48,8 @@ #include #include +#include + Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image") Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw") Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx") @@ -293,7 +295,6 @@ int networkTexturePointerMetaTypeId = qRegisterMetaType(url); @@ -309,17 +310,25 @@ static bool isLocalUrl(const QUrl& url) { NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) : Resource(url), _type(type), - _sourceIsKTX(url.path().endsWith(".ktx")), _maxNumPixels(maxNumPixels) { _textureSource = std::make_shared(url, (int)type); _lowestRequestedMipLevel = 0; - _shouldFailOnRedirect = !_sourceIsKTX; + qDebug() << "Creating networktexture: " << url; + if (url.fileName().endsWith(TEXTURE_META_EXTENSION)) { + _currentlyLoadingResourceType = ResourceType::META; + } else if (url.fileName().endsWith(".ktx")) { + _currentlyLoadingResourceType = ResourceType::KTX; + } else { + _currentlyLoadingResourceType = ResourceType::ORIGINAL; + } + + _shouldFailOnRedirect = _currentlyLoadingResourceType != ResourceType::KTX; if (type == image::TextureUsage::CUBE_TEXTURE) { setLoadPriority(this, SKYBOX_LOAD_PRIORITY); - } else if (_sourceIsKTX) { + } else if (_currentlyLoadingResourceType == ResourceType::KTX) { setLoadPriority(this, HIGH_MIPS_LOAD_PRIORITY); } @@ -330,7 +339,7 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, // if we have content, load it after we have our self pointer if (!content.isEmpty()) { _startedLoading = true; - QMetaObject::invokeMethod(this, "loadContent", Qt::QueuedConnection, Q_ARG(const QByteArray&, content)); + QMetaObject::invokeMethod(this, "downloadFinished", Qt::QueuedConnection, Q_ARG(const QByteArray&, content)); } } @@ -393,12 +402,13 @@ NetworkTexture::~NetworkTexture() { const uint16_t NetworkTexture::NULL_MIP_LEVEL = std::numeric_limits::max(); void NetworkTexture::makeRequest() { - if (!_sourceIsKTX) { + qDebug() << "In makeRequest for " << _activeUrl << (int)_currentlyLoadingResourceType; + if (_currentlyLoadingResourceType != ResourceType::KTX) { Resource::makeRequest(); return; } - if (isLocalUrl(_url)) { + if (isLocalUrl(_activeUrl)) { auto self = _self; QtConcurrent::run(QThreadPool::globalInstance(), [self] { auto resource = self.lock(); @@ -444,6 +454,7 @@ void NetworkTexture::makeRequest() { _ktxHeaderRequest->send(); + qDebug() << "Starting mip range request"; startMipRangeRequest(NULL_MIP_LEVEL, NULL_MIP_LEVEL); } else if (_ktxResourceState == PENDING_MIP_REQUEST) { if (_lowestKnownPopulatedMip > 0) { @@ -466,12 +477,12 @@ void NetworkTexture::handleLocalRequestCompleted() { } void NetworkTexture::makeLocalRequest() { - const QString scheme = _url.scheme(); + const QString scheme = _activeUrl.scheme(); QString path; if (scheme == URL_SCHEME_FILE) { - path = PathUtils::expandToLocalDataAbsolutePath(_url).toLocalFile(); + path = PathUtils::expandToLocalDataAbsolutePath(_activeUrl).toLocalFile(); } else { - path = ":" + _url.path(); + path = ":" + _activeUrl.path(); } connect(this, &Resource::finished, this, &NetworkTexture::handleLocalRequestCompleted); @@ -497,7 +508,7 @@ void NetworkTexture::makeLocalRequest() { }); if (found == ktxDescriptor->keyValues.end() || found->_value.size() != gpu::SOURCE_HASH_BYTES) { - hash = _url.toString().toLocal8Bit().toHex().toStdString(); + hash = _activeUrl.toString().toLocal8Bit().toHex().toStdString(); } else { // at this point the source hash is in binary 16-byte form // and we need it in a hexadecimal string @@ -536,11 +547,13 @@ void NetworkTexture::makeLocalRequest() { } bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) { - if (!_sourceIsKTX && result == ResourceRequest::Result::RedirectFail) { + if (_currentlyLoadingResourceType != ResourceType::KTX + && result == ResourceRequest::Result::RedirectFail) { + auto newPath = _request->getRelativePathUrl(); if (newPath.fileName().endsWith(".ktx")) { qDebug() << "Redirecting to" << newPath << "from" << _url; - _sourceIsKTX = true; + _currentlyLoadingResourceType = ResourceType::KTX; _activeUrl = newPath; _shouldFailOnRedirect = false; makeRequest(); @@ -581,6 +594,7 @@ void NetworkTexture::startMipRangeRequest(uint16_t low, uint16_t high) { bool isHighMipRequest = low == NULL_MIP_LEVEL && high == NULL_MIP_LEVEL; + qDebug() << "Making ktx mip request to: " << _activeUrl; _ktxMipRequest = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_ktxMipRequest) { @@ -930,11 +944,79 @@ void NetworkTexture::handleFinishedInitialLoad() { } void NetworkTexture::downloadFinished(const QByteArray& data) { - loadContent(data); + qDebug() << "Loading content: " << _activeUrl; + if (_currentlyLoadingResourceType == ResourceType::META) { + qDebug() << "Loading meta content: " << _activeUrl; + loadMetaContent(data); + } else if (_currentlyLoadingResourceType == ResourceType::ORIGINAL) { + loadTextureContent(data); + } else { + TextureCache::requestCompleted(_self); + Resource::handleFailedRequest(ResourceRequest::Error); + } } -void NetworkTexture::loadContent(const QByteArray& content) { - if (_sourceIsKTX) { +void NetworkTexture::loadMetaContent(const QByteArray& content) { + if (_currentlyLoadingResourceType != ResourceType::META) { + qWarning() << "Trying to load meta content when current resource type is not META"; + assert(false); + return; + } + + TextureMeta meta; + if (!TextureMeta::deserialize(content, &meta)) { + qWarning() << "Failed to read texture meta from " << _url; + return; + } + + + auto& backend = DependencyManager::get()->getGPUContext()->getBackend(); + for (auto pair : meta.availableTextureTypes) { + gpu::Element elFormat; + + if (gpu::Texture::getCompressedFormat(pair.first, elFormat)) { + if (backend->supportedTextureFormat(elFormat)) { + auto url = pair.second; + if (url.fileName().endsWith(TEXTURE_META_EXTENSION)) { + qWarning() << "Found a texture meta URL inside of the texture meta file at" << _activeUrl; + continue; + } + + _currentlyLoadingResourceType = ResourceType::KTX; + _activeUrl = _activeUrl.resolved(url); + qDebug() << "Active url is now: " << _activeUrl; + auto textureCache = DependencyManager::get(); + auto self = _self.lock(); + if (!self) { + return; + } + QMetaObject::invokeMethod(this, "attemptRequest", Qt::QueuedConnection); + return; + } + } + } + + if (!meta.original.isEmpty()) { + _currentlyLoadingResourceType = ResourceType::ORIGINAL; + _activeUrl = _activeUrl.resolved(meta.original); + + auto textureCache = DependencyManager::get(); + auto self = _self.lock(); + if (!self) { + return; + } + QMetaObject::invokeMethod(this, "attemptRequest", Qt::QueuedConnection); + return; + } + + qWarning() << "Failed to find supported texture type in " << _activeUrl; + //TextureCache::requestCompleted(_self); + Resource::handleFailedRequest(ResourceRequest::NotFound); +} + +void NetworkTexture::loadTextureContent(const QByteArray& content) { + if (_currentlyLoadingResourceType != ResourceType::ORIGINAL) { + qWarning() << "Trying to load texture content when currentl resource type is not ORIGINAL"; assert(false); return; } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 3f46dc3074..d93ddb461e 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -24,7 +24,9 @@ #include #include #include +#include +#include #include "KTXCache.h" namespace gpu { @@ -75,11 +77,13 @@ protected: virtual bool isCacheable() const override { return _loaded; } - virtual void downloadFinished(const QByteArray& data) override; + Q_INVOKABLE virtual void downloadFinished(const QByteArray& data) override; bool handleFailedRequest(ResourceRequest::Result result) override; - Q_INVOKABLE void loadContent(const QByteArray& content); + Q_INVOKABLE void loadMetaContent(const QByteArray& content); + Q_INVOKABLE void loadTextureContent(const QByteArray& content); + Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight); Q_INVOKABLE void startRequestForNextMipLevel(); @@ -93,6 +97,14 @@ private: image::TextureUsage::Type _type; + enum class ResourceType { + META, + ORIGINAL, + KTX + }; + + ResourceType _currentlyLoadingResourceType { ResourceType::META }; + static const uint16_t NULL_MIP_LEVEL; enum KTXResourceState { PENDING_INITIAL_LOAD = 0, @@ -103,7 +115,6 @@ private: FAILED_TO_LOAD }; - bool _sourceIsKTX { false }; KTXResourceState _ktxResourceState { PENDING_INITIAL_LOAD }; // The current mips that are currently being requested w/ _ktxMipRequest @@ -236,6 +247,9 @@ public: static const int DEFAULT_SPECTATOR_CAM_WIDTH { 2048 }; static const int DEFAULT_SPECTATOR_CAM_HEIGHT { 1024 }; + void setGPUContext(const gpu::ContextPointer& context) { _gpuContext = context; } + gpu::ContextPointer getGPUContext() const { return _gpuContext; } + signals: /**jsdoc * @function TextureCache.spectatorCameraFramebufferReset @@ -268,6 +282,8 @@ private: static const std::string KTX_DIRNAME; static const std::string KTX_EXT; + gpu::ContextPointer _gpuContext { nullptr }; + std::shared_ptr _ktxCache { std::make_shared(KTX_DIRNAME, KTX_EXT) }; // Map from image hashes to texture weak pointers diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 7ba7cca96d..4d3ba9da25 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -581,6 +581,7 @@ void Resource::refresh() { ResourceCache::requestCompleted(_self); } + _activeUrl = _url; init(); ensureLoading(); emit onRefresh(); @@ -618,7 +619,7 @@ void Resource::init(bool resetLoaded) { _loaded = false; } _attempts = 0; - _activeUrl = _url; + qDebug() << "Initting resource: " << _url; if (_url.isEmpty()) { _startedLoading = _loaded = true; @@ -671,6 +672,7 @@ void Resource::makeRequest() { PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } }); + qDebug() << "Making request to " << _activeUrl; _request = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_request) { @@ -724,7 +726,7 @@ void Resource::handleReplyFinished() { auto result = _request->getResult(); if (result == ResourceRequest::Success) { auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString()); - qCDebug(networking).noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo); + qCDebug(networking).noquote() << QString("Request finished for %1%2").arg(_activeUrl.toDisplayString(), extraInfo); auto relativePathURL = _request->getRelativePathUrl(); if (!relativePathURL.isEmpty()) { diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index 3c6799db88..0a75c72f9a 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -464,7 +464,7 @@ bool DomainBaker::rewriteSkyboxURL(QJsonValueRef urlValue, TextureBaker* baker) if (oldSkyboxURL.matches(baker->getTextureURL(), QUrl::RemoveQuery | QUrl::RemoveFragment)) { // change the URL to point to the baked texture with its original query and fragment - auto newSkyboxURL = _destinationPath.resolved(baker->getBakedTextureFileName()); + auto newSkyboxURL = _destinationPath.resolved(baker->getMetaTextureFileName()); newSkyboxURL.setQuery(oldSkyboxURL.query()); newSkyboxURL.setFragment(oldSkyboxURL.fragment()); newSkyboxURL.setUserInfo(oldSkyboxURL.userInfo()); From 12d4cf12cf6790a5d9549df29bc3718648a32994 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 1 May 2018 14:11:50 -0700 Subject: [PATCH 055/174] Bump model and texture baking versions in AssetServer --- assignment-client/src/assets/AssetServer.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index fb88df0171..c4b1ff07e5 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -36,10 +36,11 @@ enum class BakedAssetType : int { Undefined }; -// ATTENTION! If you change the current version for an asset type, you will also -// need to update the function currentBakeVersionForAssetType() inside of AssetServer.cpp. +// ATTENTION! Do not remove baking versions, and do not reorder them. If you add +// a new value, it will immediately become the "current" version. enum class ModelBakeVersion : BakeVersion { Initial = INITIAL_BAKE_VERSION, + MetaTextureJson, COUNT }; @@ -47,6 +48,7 @@ enum class ModelBakeVersion : BakeVersion { // ATTENTION! See above. enum class TextureBakeVersion : BakeVersion { Initial = INITIAL_BAKE_VERSION, + MetaTextureJson, COUNT }; From b722c80b3f9f367fdc5758064c4110ecc8216221 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 1 May 2018 14:25:33 -0700 Subject: [PATCH 056/174] WIP --- tools/auto-tester/src/ui/AutoTester.cpp | 12 ++++++++---- tools/auto-tester/src/ui/AutoTester.h | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 3f7d2cba28..860868565a 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -10,8 +10,6 @@ // #include "AutoTester.h" -#include - AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); ui.checkBoxInteractiveMode->setChecked(true); @@ -91,11 +89,17 @@ void AutoTester::saveImage(int index) { QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); + int sdf = pixmap.width(); QImage image = pixmap.toImage(); image = image.convertToFormat(QImage::Format_ARGB32); QString fullPathname = _directoryName + "/" + _filenames[index]; - image.save(fullPathname, 0, 100); + if (!image.save(fullPathname, 0, 100)) { + QMessageBox messageBox; + messageBox.information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); + ui.progressBar->setVisible(false); + return; + } ++_numberOfImagesDownloaded; @@ -109,4 +113,4 @@ void AutoTester::saveImage(int index) { void AutoTester::about() { QMessageBox messageBox; messageBox.information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); -} \ No newline at end of file +} diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index 03cb7fbcec..d911b6aaff 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -52,9 +52,9 @@ private: // Used to enable passing a parameter to slots QSignalMapper* signalMapper; - int _numberOfImagesToDownload; - int _numberOfImagesDownloaded; - int _index; + int _numberOfImagesToDownload { 0 }; + int _numberOfImagesDownloaded { 0 }; + int _index { 0 }; }; #endif // hifi_AutoTester_h \ No newline at end of file From 0653f49efe1b2ff75c4f8ad7ef4045d89b2c02f4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 May 2018 09:31:24 +1200 Subject: [PATCH 057/174] Remove deprecated location.domainId from API location.domainID is available, instead. --- libraries/networking/src/AddressManager.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 94eff46bda..95bf0c18a8 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -36,8 +36,6 @@ const QString GET_PLACE = "/api/v1/places/%1"; * @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not * connected to the domain or are in a serverless domain. * Read-only. - * @property {Uuid} domainId - Synonym for domainId. Read-only. Deprecated: This property - * is deprecated and will soon be removed. * @property {string} hostname - The name of the domain for your current metaverse address (e.g., "AvatarIsland", * localhost, or an IP address). Is blank if you're in a serverless domain. * Read-only. @@ -68,7 +66,6 @@ class AddressManager : public QObject, public Dependency { Q_PROPERTY(QString pathname READ currentPath) Q_PROPERTY(QString placename READ getPlaceName) Q_PROPERTY(QString domainID READ getDomainID) - Q_PROPERTY(QString domainId READ getDomainID) public: using PositionGetter = std::function; using OrientationGetter = std::function; From d1bb37874d0ca832fea0d3d78472ce14b3115ef8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 30 Apr 2018 17:13:44 -0700 Subject: [PATCH 058/174] Prevent crash in ImageProvider when tablet isn't yet initialized --- interface/src/commerce/Wallet.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 3e0e4adf18..42c8b9973d 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -615,9 +615,12 @@ void Wallet::updateImageProvider() { securityImageProvider->setSecurityImage(_securityImage); // inform tablet security image provider - QQmlEngine* tabletEngine = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")->getTabletSurface()->getSurfaceContext()->engine(); - securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); - securityImageProvider->setSecurityImage(_securityImage); + auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + if (tablet) { + QQmlEngine* tabletEngine = tablet->getTabletSurface()->getSurfaceContext()->engine(); + securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); + securityImageProvider->setSecurityImage(_securityImage); + } } void Wallet::chooseSecurityImage(const QString& filename) { From d5f809c3c08730a3016c772a4b710fd8e7b10d85 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 1 May 2018 09:54:23 -0700 Subject: [PATCH 059/174] Actually fix --- interface/src/commerce/Wallet.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 42c8b9973d..35e6ca1c92 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -615,11 +615,14 @@ void Wallet::updateImageProvider() { securityImageProvider->setSecurityImage(_securityImage); // inform tablet security image provider - auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + TabletProxy* tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); if (tablet) { - QQmlEngine* tabletEngine = tablet->getTabletSurface()->getSurfaceContext()->engine(); - securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); - securityImageProvider->setSecurityImage(_securityImage); + OffscreenQmlSurface* tabletSurface = tablet->getTabletSurface(); + if (tabletSurface) { + QQmlEngine* tabletEngine = tabletSurface->getSurfaceContext()->engine(); + securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); + securityImageProvider->setSecurityImage(_securityImage); + } } } From a3e4fa84292ab1607ed6cca3a10003ed75825595 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 1 May 2018 15:27:29 -0700 Subject: [PATCH 060/174] Corrected download of images. --- tools/auto-tester/src/Downloader.cpp | 9 +++++++++ tools/auto-tester/src/Test.cpp | 7 +++++-- tools/auto-tester/src/ui/AutoTester.cpp | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/auto-tester/src/Downloader.cpp b/tools/auto-tester/src/Downloader.cpp index 030aa95a19..e66b498bd5 100644 --- a/tools/auto-tester/src/Downloader.cpp +++ b/tools/auto-tester/src/Downloader.cpp @@ -9,6 +9,8 @@ // #include "Downloader.h" +#include + Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { connect( &_networkAccessManager, SIGNAL (finished(QNetworkReply*)), @@ -20,6 +22,13 @@ Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { } void Downloader::fileDownloaded(QNetworkReply* reply) { + QNetworkReply::NetworkError error = reply->error(); + if (error != QNetworkReply::NetworkError::NoError) { + QMessageBox messageBox; + messageBox.information(0, "Test Aborted", "Failed to download image: " + reply->errorString()); + return; + } + _downloadedData = reply->readAll(); //emit a signal diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 57806e80f6..d0a1606cd8 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -221,8 +221,11 @@ void Test::startTestsEvaluation() { QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS); QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png"; - QString imageURLString("https://github.com/" + githubUser + "/hifi_tests/blob/" + gitHubBranch + "/" + - expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename + "?raw=true"); + //https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/content/entity/zone/zoneOrientation/ExpectedImage_00001.png + + + QString imageURLString("https://raw.githubusercontent.com/" + githubUser + "/hifi_tests/" + gitHubBranch + "/" + + expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename); expectedImagesURLs << imageURLString; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 860868565a..17b1513467 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -86,6 +86,7 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director } void AutoTester::saveImage(int index) { + QByteArray q = downloaders[index]->downloadedData(); QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); From 521ae36cbf9fb2f8dc197e150e2b28c1a78e1f40 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 15:29:22 -0700 Subject: [PATCH 061/174] Make resource swapchains immutable, fix for 14638 --- .../src/gpu/gl/GLBackendOutput.cpp | 4 ++-- .../src/gpu/gl/GLBackendPipeline.cpp | 9 ++++---- libraries/gpu/src/gpu/ResourceSwapChain.h | 19 +++++++---------- .../render-utils/src/AntialiasingEffect.cpp | 21 +++++++++---------- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 2285b0e486..d1ab34da90 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -46,10 +46,10 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { } void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) { - auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset]._uint)); if (swapChain) { auto index = batch._params[paramOffset + 1]._uint; - FramebufferPointer framebuffer = static_cast(swapChain.get())->get(index); + const auto& framebuffer = swapChain->get(index); setFramebuffer(framebuffer); } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp index 237b8bc1e9..d5cb331a4a 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp @@ -1,4 +1,4 @@ -// +// // GLBackendPipeline.cpp // libraries/gpu/src/gpu // @@ -263,7 +263,7 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si return; } - SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset + 0]._uint)); if (!swapChain) { releaseResourceTexture(slot); @@ -271,9 +271,8 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si } auto index = batch._params[paramOffset + 2]._uint; auto renderBufferSlot = batch._params[paramOffset + 3]._uint; - FramebufferPointer resourceFramebuffer = static_cast(swapChain.get())->get(index); - TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); - + auto resourceFramebuffer = swapChain->get(index); + auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); setResourceTexture(slot, resourceTexture); } diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 7b46b35521..84e8ec7c74 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(unsigned int size = 2U) : _size{ size } {} + SwapChain(size_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - unsigned int getSize() const { return _size; } + size_t getSize() const { return _size; } protected: - unsigned int _size; - unsigned int _frontIndex{ 0U }; + const size_t _size; + size_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -41,16 +41,13 @@ namespace gpu { using Type = R; using TypePointer = std::shared_ptr; + using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(unsigned int size = 2U) : SwapChain{ size } {} - - void reset() { - for (auto& ptr : _resources) { - ptr.reset(); + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + for (size_t i = 0; i < _size; ++i) { + _resources[i] = v[i]; } } - - TypePointer& edit(unsigned int index) { return _resources[(index + _frontIndex) % _size]; } const TypePointer& get(unsigned int index) const { return _resources[(index + _frontIndex) % _size]; } private: diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index ba5036ad68..357782a321 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -188,7 +188,6 @@ const int AntialiasingPass_NextMapSlot = 4; Antialiasing::Antialiasing() { - _antialiasingBuffers = std::make_shared(2U); } Antialiasing::~Antialiasing() { @@ -317,25 +316,25 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const int width = sourceBuffer->getWidth(); int height = sourceBuffer->getHeight(); - if (_antialiasingBuffers->get(0)) { - if (_antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {// || (sourceBuffer && (_antialiasingBuffer->getRenderBuffer(1) != sourceBuffer->getRenderBuffer(0)))) { - _antialiasingBuffers->edit(0).reset(); - _antialiasingBuffers->edit(1).reset(); - _antialiasingTextures[0].reset(); - _antialiasingTextures[1].reset(); - } + if (_antialiasingBuffers && _antialiasingBuffers->get(0) && _antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) { + _antialiasingBuffers.reset(); + _antialiasingTextures[0].reset(); + _antialiasingTextures[1].reset(); } - if (!_antialiasingBuffers->get(0)) { + + if (!_antialiasingBuffers) { + std::vector antiAliasingBuffers; // Link the antialiasing FBO to texture for (int i = 0; i < 2; i++) { - auto& antiAliasingBuffer = _antialiasingBuffers->edit(i); - antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing")); + antiAliasingBuffers.emplace_back(gpu::Framebuffer::create("antialiasing")); + const auto& antiAliasingBuffer = antiAliasingBuffers.back(); auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get()->getLightingTexture()->getTexelFormat(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); _antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]); } + _antialiasingBuffers = std::make_shared(antiAliasingBuffers); } gpu::doInBatch("Antialiasing::run", args->_context, [&](gpu::Batch& batch) { From fb929da2280ad3a45c32a41130a5ebeeb31e6160 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 16:54:26 -0700 Subject: [PATCH 062/174] Change type used for swap chain count --- libraries/gpu/src/gpu/ResourceSwapChain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 84e8ec7c74..28c5ff2ed3 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(size_t size = 2U) : _size{ size } {} + SwapChain(uint8_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - size_t getSize() const { return _size; } + uint8_t getSize() const { return _size; } protected: - const size_t _size; - size_t _frontIndex{ 0U }; + const uint8_t _size; + uint8_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -43,7 +43,7 @@ namespace gpu { using TypePointer = std::shared_ptr; using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min((uint8_t)v.size(), MAX_SIZE) } { for (size_t i = 0; i < _size; ++i) { _resources[i] = v[i]; } From 93afbcdc08f42f68e4c0f9417279bd012f69643f Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 1 May 2018 17:59:07 -0700 Subject: [PATCH 063/174] First success with running from command line. --- tools/auto-tester/src/Test.cpp | 53 ++++++++++++++----------- tools/auto-tester/src/Test.h | 29 +++++++------- tools/auto-tester/src/main.cpp | 15 ++++++- tools/auto-tester/src/ui/AutoTester.cpp | 12 ++++-- tools/auto-tester/src/ui/AutoTester.h | 5 +++ 5 files changed, 70 insertions(+), 44 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index d0a1606cd8..7139f0a43c 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -27,7 +27,7 @@ Test::Test() { mismatchWindow.setModal(true); } -bool Test::createTestResultsFolderPath(QString directory) { +bool Test::createTestResultsFolderPath(const QString& directory) { QDateTime now = QDateTime::currentDateTime(); testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER + "--" + now.toString(DATETIME_FORMAT); QDir testResultsFolder(testResultsFolderPath); @@ -125,7 +125,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) return success; } -void Test::appendTestResultsToFile(QString testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { +void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { if (!QDir().exists(testResultsFolderPath)) { messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); exit(-1); @@ -174,10 +174,16 @@ void Test::appendTestResultsToFile(QString testResultsFolderPath, TestFailure te comparisonImage.save(failureFolderPath + "/" + "Difference Image.jpg"); } -void Test::startTestsEvaluation() { - // Get list of JPEG images in folder, sorted by name - pathToTestResultsDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly); - if (pathToTestResultsDirectory == "") { +void Test::startTestsEvaluation(const QString& testFolder) { + QString pathToTestResultsDirectory; + if (testFolder.isNull()) { + // Get list of JPEG images in folder, sorted by name + pathToTestResultsDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly); + } else { + pathToTestResultsDirectory = testFolder; + } + + if (pathToTestResultsDirectory == QString()) { return; } @@ -221,9 +227,6 @@ void Test::startTestsEvaluation() { QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS); QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png"; - //https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/content/entity/zone/zoneOrientation/ExpectedImage_00001.png - - QString imageURLString("https://raw.githubusercontent.com/" + githubUser + "/hifi_tests/" + gitHubBranch + "/" + expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename); @@ -240,19 +243,21 @@ void Test::startTestsEvaluation() { autoTester->downloadImages(expectedImagesURLs, pathToTestResultsDirectory, expectedImagesFilenames); } -void Test::finishTestsEvaluation(bool interactiveMode, QProgressBar* progressBar) { - bool success = compareImageLists(interactiveMode, progressBar); +void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) { + bool success = compareImageLists((!isRunningFromCommandline && interactiveMode), progressBar); - if (success) { - messageBox.information(0, "Success", "All images are as expected"); - } else { - messageBox.information(0, "Failure", "One or more images are not as expected"); + if (!isRunningFromCommandline) { + if (success) { + messageBox.information(0, "Success", "All images are as expected"); + } else { + messageBox.information(0, "Failure", "One or more images are not as expected"); + } } zipAndDeleteTestResultsFolder(); } -bool Test::isAValidDirectory(QString pathname) { +bool Test::isAValidDirectory(const QString& pathname) { // Only process directories QDir dir(pathname); if (!dir.exists()) { @@ -267,7 +272,7 @@ bool Test::isAValidDirectory(QString pathname) { return true; } -QString Test::extractPathFromTestsDown(QString fullPath) { +QString Test::extractPathFromTestsDown(const QString& fullPath) { // `fullPath` includes the full path to the test. We need the portion below (and including) `tests` QStringList pathParts = fullPath.split('/'); int i{ 0 }; @@ -348,7 +353,7 @@ void Test::createAllRecursiveScripts() { messageBox.information(0, "Success", "Scripts have been created"); } -void Test::createRecursiveScript(QString topLevelDirectory, bool interactiveMode) { +void Test::createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode) { const QString recursiveTestsFilename("testRecursive.js"); QFile allTestsFilename(topLevelDirectory + "/" + recursiveTestsFilename); if (!allTestsFilename.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -615,7 +620,7 @@ void Test::createAllMDFiles() { messageBox.information(0, "Success", "MD files have been created"); } -void Test::createMDFile(QString testDirectory) { +void Test::createMDFile(const QString& testDirectory) { // Verify folder contains test.js file QString testFileName(testDirectory + "/" + TEST_FILENAME); QFileInfo testFileInfo(testFileName); @@ -790,7 +795,7 @@ void Test::createTestsOutline() { messageBox.information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); } -void Test::copyJPGtoPNG(QString sourceJPGFullFilename, QString destinationPNGFullFilename) { +void Test::copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename) { QFile::remove(destinationPNGFullFilename); QImageReader reader; @@ -803,7 +808,7 @@ void Test::copyJPGtoPNG(QString sourceJPGFullFilename, QString destinationPNGFul writer.write(image); } -QStringList Test::createListOfAll_imagesInDirectory(QString imageFormat, QString pathToImageDirectory) { +QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { imageDirectory = QDir(pathToImageDirectory); QStringList nameFilters; nameFilters << "*." + imageFormat; @@ -816,7 +821,7 @@ QStringList Test::createListOfAll_imagesInDirectory(QString imageFormat, QString // Filename (i.e. without extension) contains _tests_ (this is based on all test scripts being within the tests folder // Last 5 characters in filename are digits // Extension is jpg -bool Test::isInSnapshotFilenameFormat(QString imageFormat, QString filename) { +bool Test::isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename) { QStringList filenameParts = filename.split("."); bool filnameHasNoPeriods = (filenameParts.size() == 2); @@ -833,7 +838,7 @@ bool Test::isInSnapshotFilenameFormat(QString imageFormat, QString filename) { // For a file named "D_GitHub_hifi-tests_tests_content_entity_zone_create_0.jpg", the test directory is // D:/GitHub/hifi-tests/tests/content/entity/zone/create // This method assumes the filename is in the correct format -QString Test::getExpectedImageDestinationDirectory(QString filename) { +QString Test::getExpectedImageDestinationDirectory(const QString& filename) { QString filenameWithoutExtension = filename.split(".")[0]; QStringList filenameParts = filenameWithoutExtension.split("_"); @@ -850,7 +855,7 @@ QString Test::getExpectedImageDestinationDirectory(QString filename) { // is ...tests/content/entity/zone/create // This is used to create the full URL // This method assumes the filename is in the correct format -QString Test::getExpectedImagePartialSourceDirectory(QString filename) { +QString Test::getExpectedImagePartialSourceDirectory(const QString& filename) { QString filenameWithoutExtension = filename.split(".")[0]; QStringList filenameParts = filenameWithoutExtension.split("_"); diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 7f5553f9e3..02cab53381 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -43,39 +43,39 @@ class Test { public: Test(); - void startTestsEvaluation(); - void finishTestsEvaluation(bool interactiveMode, QProgressBar* progressBar); + void startTestsEvaluation(const QString& testFolder = QString()); + void finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar); void createRecursiveScript(); void createAllRecursiveScripts(); - void createRecursiveScript(QString topLevelDirectory, bool interactiveMode); + void createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode); void createTest(); void createMDFile(); void createAllMDFiles(); - void createMDFile(QString topLevelDirectory); + void createMDFile(const QString& topLevelDirectory); void createTestsOutline(); bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar); - QStringList createListOfAll_imagesInDirectory(QString imageFormat, QString pathToImageDirectory); + QStringList createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory); - bool isInSnapshotFilenameFormat(QString imageFormat, QString filename); + bool isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename); void importTest(QTextStream& textStream, const QString& testPathname); - void appendTestResultsToFile(QString testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage); + void appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage); - bool createTestResultsFolderPath(QString directory); + bool createTestResultsFolderPath(const QString& directory); void zipAndDeleteTestResultsFolder(); - bool isAValidDirectory(QString pathname); - QString extractPathFromTestsDown(QString fullPath); - QString getExpectedImageDestinationDirectory(QString filename); - QString getExpectedImagePartialSourceDirectory(QString filename); + bool isAValidDirectory(const QString& pathname); + QString extractPathFromTestsDown(const QString& fullPath); + QString getExpectedImageDestinationDirectory(const QString& filename); + QString getExpectedImagePartialSourceDirectory(const QString& filename); - void copyJPGtoPNG(QString sourceJPGFullFilename, QString destinationPNGFullFilename); + void copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename); private: const QString TEST_FILENAME { "test.js" }; @@ -90,14 +90,13 @@ private: ImageComparer imageComparer; - QString testResultsFolderPath { "" }; + QString testResultsFolderPath; int index { 1 }; // Expected images are in the format ExpectedImage_dddd.jpg (d == decimal digit) const int NUM_DIGITS { 5 }; const QString EXPECTED_IMAGE_PREFIX { "ExpectedImage_" }; - QString pathToTestResultsDirectory; QStringList expectedImagesFilenames; QStringList expectedImagesFullFilenames; QStringList resultImagesFullFilenames; diff --git a/tools/auto-tester/src/main.cpp b/tools/auto-tester/src/main.cpp index cd0ce22b13..ffa7a0b237 100644 --- a/tools/auto-tester/src/main.cpp +++ b/tools/auto-tester/src/main.cpp @@ -13,10 +13,23 @@ AutoTester* autoTester; int main(int argc, char *argv[]) { + // Only parameter is "--testFolder" + QString testFolder; + if (argc == 3) { + if (QString(argv[1]) == "--testFolder") { + testFolder = QString(argv[2]); + } + } + QApplication application(argc, argv); autoTester = new AutoTester(); - autoTester->show(); + + if (!testFolder.isNull()) { + autoTester->runFromCommandLine(testFolder); + } else { + autoTester->show(); + } return application.exec(); } diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 17b1513467..e0f92664ef 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -15,12 +15,17 @@ AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { ui.checkBoxInteractiveMode->setChecked(true); ui.progressBar->setVisible(false); - test = new Test(); - signalMapper = new QSignalMapper(); connect(ui.actionClose, &QAction::triggered, this, &AutoTester::on_closeButton_clicked); connect(ui.actionAbout, &QAction::triggered, this, &AutoTester::about); + + test = new Test(); +} + +void AutoTester::runFromCommandLine(const QString& testFolder) { + isRunningFromCommandline = true; + test->startTestsEvaluation(testFolder); } void AutoTester::on_evaluateTestsButton_clicked() { @@ -86,7 +91,6 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director } void AutoTester::saveImage(int index) { - QByteArray q = downloaders[index]->downloadedData(); QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); @@ -105,7 +109,7 @@ void AutoTester::saveImage(int index) { ++_numberOfImagesDownloaded; if (_numberOfImagesDownloaded == _numberOfImagesToDownload) { - test->finishTestsEvaluation(ui.checkBoxInteractiveMode->isChecked(), ui.progressBar); + test->finishTestsEvaluation(isRunningFromCommandline, ui.checkBoxInteractiveMode->isChecked(), ui.progressBar); } else { ui.progressBar->setValue(_numberOfImagesDownloaded); } diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index d911b6aaff..fe37f2298d 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -22,6 +22,9 @@ class AutoTester : public QMainWindow { public: AutoTester(QWidget *parent = Q_NULLPTR); + + void runFromCommandLine(const QString& testFolder); + void downloadImage(const QUrl& url); void downloadImages(const QStringList& URLs, const QString& directoryName, const QStringList& filenames); @@ -55,6 +58,8 @@ private: int _numberOfImagesToDownload { 0 }; int _numberOfImagesDownloaded { 0 }; int _index { 0 }; + + bool isRunningFromCommandline { false }; }; #endif // hifi_AutoTester_h \ No newline at end of file From 49fad3d8685dc7a5d430b27574ee4b7525d0c7d8 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 13 Apr 2018 18:01:54 -0700 Subject: [PATCH 064/174] EntityServer traversal aware of all ViewFrustums --- .../src/entities/EntityPriorityQueue.cpp | 23 +++- .../src/entities/EntityPriorityQueue.h | 16 ++- .../src/entities/EntityTreeSendThread.cpp | 100 +++++++-------- .../src/entities/EntityTreeSendThread.h | 3 +- .../src/octree/OctreeHeadlessViewer.cpp | 9 +- .../src/octree/OctreeSendThread.cpp | 6 +- .../src/scripts/EntityScriptServer.cpp | 1 - interface/src/Application.cpp | 10 +- libraries/entities/src/DiffTraversal.cpp | 121 +++++++++++++----- libraries/entities/src/DiffTraversal.h | 20 +-- libraries/octree/src/Octree.h | 1 - libraries/octree/src/OctreeQuery.cpp | 107 +++++++--------- libraries/octree/src/OctreeQuery.h | 63 +++------ libraries/octree/src/OctreeQueryNode.cpp | 111 +++++++--------- libraries/octree/src/OctreeQueryNode.h | 9 +- libraries/octree/src/OctreeUtils.cpp | 9 +- libraries/octree/src/OctreeUtils.h | 3 + libraries/shared/src/ViewFrustum.cpp | 4 +- libraries/shared/src/ViewFrustum.h | 2 +- 19 files changed, 322 insertions(+), 296 deletions(-) diff --git a/assignment-client/src/entities/EntityPriorityQueue.cpp b/assignment-client/src/entities/EntityPriorityQueue.cpp index 999a05f2e2..a38d537649 100644 --- a/assignment-client/src/entities/EntityPriorityQueue.cpp +++ b/assignment-client/src/entities/EntityPriorityQueue.cpp @@ -15,7 +15,7 @@ const float PrioritizedEntity::DO_NOT_SEND = -1.0e-6f; const float PrioritizedEntity::FORCE_REMOVE = -1.0e-5f; const float PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY = 1.0f; -void ConicalView::set(const ViewFrustum& viewFrustum) { +void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) { // The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part. // Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum. _position = viewFrustum.getPosition(); @@ -31,7 +31,7 @@ void ConicalView::set(const ViewFrustum& viewFrustum) { _radius = viewFrustum.getCenterRadius(); } -float ConicalView::computePriority(const AACube& cube) const { +float ConicalViewFrustum::computePriority(const AACube& cube) const { glm::vec3 p = cube.calcCenter() - _position; // position of bounding sphere in view-frame float d = glm::length(p); // distance to center of bounding sphere float r = 0.5f * cube.getScale(); // radius of bounding sphere @@ -51,3 +51,22 @@ float ConicalView::computePriority(const AACube& cube) const { } return PrioritizedEntity::DO_NOT_SEND; } + + +void ConicalView::set(const DiffTraversal::View& view) { + auto size = view.viewFrustums.size(); + _conicalViewFrustums.resize(size); + for (size_t i = 0; i < size; ++i) { + _conicalViewFrustums[i].set(view.viewFrustums[i]); + } +} + +float ConicalView::computePriority(const AACube& cube) const { + float priority = PrioritizedEntity::DO_NOT_SEND; + + for (const auto& view : _conicalViewFrustums) { + priority = std::max(priority, view.computePriority(cube)); + } + + return priority; +} diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/assignment-client/src/entities/EntityPriorityQueue.h index e308d9b549..4068b4dc4b 100644 --- a/assignment-client/src/entities/EntityPriorityQueue.h +++ b/assignment-client/src/entities/EntityPriorityQueue.h @@ -15,16 +15,17 @@ #include #include +#include #include const float SQRT_TWO_OVER_TWO = 0.7071067811865f; const float DEFAULT_VIEW_RADIUS = 10.0f; // ConicalView is an approximation of a ViewFrustum for fast calculation of sort priority. -class ConicalView { +class ConicalViewFrustum { public: - ConicalView() {} - ConicalView(const ViewFrustum& viewFrustum) { set(viewFrustum); } + ConicalViewFrustum() {} + ConicalViewFrustum(const ViewFrustum& viewFrustum) { set(viewFrustum); } void set(const ViewFrustum& viewFrustum); float computePriority(const AACube& cube) const; private: @@ -35,6 +36,15 @@ private: float _radius { DEFAULT_VIEW_RADIUS }; }; +class ConicalView { +public: + ConicalView() {} + void set(const DiffTraversal::View& view); + float computePriority(const AACube& cube) const; +private: + std::vector _conicalViewFrustums; +}; + // PrioritizedEntity is a placeholder in a sorted queue. class PrioritizedEntity { public: diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 4aa52922c0..d14d31bd09 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -103,11 +103,25 @@ void EntityTreeSendThread::preDistributionProcessing() { void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene) { if (viewFrustumChanged || _traversal.finished()) { - ViewFrustum viewFrustum; - nodeData->copyCurrentViewFrustum(viewFrustum); EntityTreeElementPointer root = std::dynamic_pointer_cast(_myServer->getOctree()->getRoot()); + + + DiffTraversal::View newView; + + ViewFrustum viewFrustum; + if (nodeData->hasMainViewFrustum()) { + nodeData->copyCurrentMainViewFrustum(viewFrustum); + newView.viewFrustums.push_back(viewFrustum); + } + if (nodeData->hasSecondaryViewFrustum()) { + nodeData->copyCurrentSecondaryViewFrustum(viewFrustum); + newView.viewFrustums.push_back(viewFrustum); + } + int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum()); + newView.lodScaleFactor = powf(2.0f, lodLevelOffset); + + startNewTraversal(newView, root); // When the viewFrustum changed the sort order may be incorrect, so we re-sort // and also use the opportunity to cull anything no longer in view @@ -116,8 +130,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O _sendQueue.swap(prevSendQueue); _entitiesInQueue.clear(); // Re-add elements from previous traversal if they still need to be sent - float lodScaleFactor = _traversal.getCurrentLODScaleFactor(); - glm::vec3 viewPosition = _traversal.getCurrentView().getPosition(); while (!prevSendQueue.empty()) { EntityItemPointer entity = prevSendQueue.top().getEntity(); bool forceRemove = prevSendQueue.top().shouldForceRemove(); @@ -127,12 +139,10 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { - if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) { + if (_traversal.getCurrentView().intersects(cube)) { float priority = _conicalView.computePriority(cube); if (priority != PrioritizedEntity::DO_NOT_SEND) { - float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE; - float angularDiameter = cube.getScale() / distance; - if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) { + if (_traversal.getCurrentView().isBigEnough(cube)) { _sendQueue.push(PrioritizedEntity(entity, priority)); _entitiesInQueue.insert(entity.get()); } @@ -215,10 +225,9 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil return hasNewChild || hasNewDescendants; } -void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum) { +void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) { - DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum); + DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root); // there are three types of traversal: // // (1) FirstTime = at login --> find everything in view @@ -236,11 +245,9 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree case DiffTraversal::First: // When we get to a First traversal, clear the _knownState _knownState.clear(); - if (usesViewFrustum) { - float lodScaleFactor = _traversal.getCurrentLODScaleFactor(); - glm::vec3 viewPosition = _traversal.getCurrentView().getPosition(); - _traversal.setScanCallback([=](DiffTraversal::VisibleElement& next) { - next.element->forEachEntity([=](EntityItemPointer entity) { + if (view.usesViewFrustums()) { + _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { + next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; @@ -248,14 +255,12 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { - if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) { + if (_traversal.getCurrentView().intersects(cube)) { // Check the size of the entity, it's possible that a "too small to see" entity is included in a // larger octree cell because of its position (for example if it crosses the boundary of a cell it // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen // before we consider including it. - float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE; - float angularDiameter = cube.getScale() / distance; - if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) { + if (_traversal.getCurrentView().isBigEnough(cube)) { float priority = _conicalView.computePriority(cube); _sendQueue.push(PrioritizedEntity(entity, priority)); _entitiesInQueue.insert(entity.get()); @@ -269,7 +274,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree }); } else { _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { - next.element->forEachEntity([this](EntityItemPointer entity) { + next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; @@ -281,13 +286,11 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree } break; case DiffTraversal::Repeat: - if (usesViewFrustum) { - float lodScaleFactor = _traversal.getCurrentLODScaleFactor(); - glm::vec3 viewPosition = _traversal.getCurrentView().getPosition(); - _traversal.setScanCallback([=](DiffTraversal::VisibleElement& next) { + if (view.usesViewFrustums()) { + _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal(); if (next.element->getLastChangedContent() > startOfCompletedTraversal) { - next.element->forEachEntity([=](EntityItemPointer entity) { + next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; @@ -297,11 +300,10 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { - if (next.intersection == ViewFrustum::INSIDE || _traversal.getCurrentView().cubeIntersectsKeyhole(cube)) { + if (next.intersection == ViewFrustum::INSIDE || + _traversal.getCurrentView().intersects(cube)) { // See the DiffTraversal::First case for an explanation of the "entity is too small" check - float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE; - float angularDiameter = cube.getScale() / distance; - if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) { + if (_traversal.getCurrentView().isBigEnough(cube)) { float priority = _conicalView.computePriority(cube); _sendQueue.push(PrioritizedEntity(entity, priority)); _entitiesInQueue.insert(entity.get()); @@ -325,7 +327,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal(); if (next.element->getLastChangedContent() > startOfCompletedTraversal) { - next.element->forEachEntity([this](EntityItemPointer entity) { + next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; @@ -343,13 +345,9 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree } break; case DiffTraversal::Differential: - assert(usesViewFrustum); - float lodScaleFactor = _traversal.getCurrentLODScaleFactor(); - glm::vec3 viewPosition = _traversal.getCurrentView().getPosition(); - float completedLODScaleFactor = _traversal.getCompletedLODScaleFactor(); - glm::vec3 completedViewPosition = _traversal.getCompletedView().getPosition(); - _traversal.setScanCallback([=] (DiffTraversal::VisibleElement& next) { - next.element->forEachEntity([=](EntityItemPointer entity) { + assert(view.usesViewFrustums()); + _traversal.setScanCallback([this] (DiffTraversal::VisibleElement& next) { + next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; @@ -359,25 +357,19 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { - if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) { + if (_traversal.getCurrentView().intersects(cube)) { // See the DiffTraversal::First case for an explanation of the "entity is too small" check - float distance = glm::distance(cube.calcCenter(), viewPosition) + MIN_VISIBLE_DISTANCE; - float angularDiameter = cube.getScale() / distance; - if (angularDiameter > MIN_ENTITY_ANGULAR_DIAMETER * lodScaleFactor) { - if (!_traversal.getCompletedView().cubeIntersectsKeyhole(cube)) { + if (_traversal.getCurrentView().isBigEnough(cube)) { + if (!_traversal.getCompletedView().intersects(cube)) { float priority = _conicalView.computePriority(cube); _sendQueue.push(PrioritizedEntity(entity, priority)); _entitiesInQueue.insert(entity.get()); - } else { + } else if (!_traversal.getCompletedView().isBigEnough(cube)) { // If this entity was skipped last time because it was too small, we still need to send it - distance = glm::distance(cube.calcCenter(), completedViewPosition) + MIN_VISIBLE_DISTANCE; - angularDiameter = cube.getScale() / distance; - if (angularDiameter <= MIN_ENTITY_ANGULAR_DIAMETER * completedLODScaleFactor) { - // this object was skipped in last completed traversal - float priority = _conicalView.computePriority(cube); - _sendQueue.push(PrioritizedEntity(entity, priority)); - _entitiesInQueue.insert(entity.get()); - } + // this object was skipped in last completed traversal + float priority = _conicalView.computePriority(cube); + _sendQueue.push(PrioritizedEntity(entity, priority)); + _entitiesInQueue.insert(entity.get()); } } } @@ -506,7 +498,7 @@ void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) AACube cube = entity->getQueryAACube(success); if (success) { // We can force a removal from _knownState if the current view is used and entity is out of view - if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) { + if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) { _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::FORCE_REMOVE, true)); _entitiesInQueue.insert(entity.get()); } diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 1e2bd15429..5ea723c8b2 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -41,8 +41,7 @@ private: bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); - void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum); + void startNewTraversal(const DiffTraversal::View& viewFrustum, EntityTreeElementPointer root); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; void preDistributionProcessing() override; diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.cpp b/assignment-client/src/octree/OctreeHeadlessViewer.cpp index d3b20fb623..4f022ae838 100644 --- a/assignment-client/src/octree/OctreeHeadlessViewer.cpp +++ b/assignment-client/src/octree/OctreeHeadlessViewer.cpp @@ -23,14 +23,7 @@ void OctreeHeadlessViewer::queryOctree() { char serverType = getMyNodeType(); PacketType packetType = getMyQueryMessageType(); - _octreeQuery.setCameraPosition(_viewFrustum.getPosition()); - _octreeQuery.setCameraOrientation(_viewFrustum.getOrientation()); - _octreeQuery.setCameraFov(_viewFrustum.getFieldOfView()); - _octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); - _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); - _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); - _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); - _octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius()); + _octreeQuery.setMainViewFrustum(_viewFrustum); _octreeQuery.setOctreeSizeScale(_voxelSizeScale); _octreeQuery.setBoundaryLevelAdjust(_boundaryLevelAdjust); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index de49bd461c..40c052659d 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -330,8 +330,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* } else { // we aren't forcing a full scene, check if something else suggests we should isFullScene = nodeData->haveJSONParametersChanged() || - (nodeData->getUsesFrustum() - && ((!viewFrustumChanged && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged())); + (nodeData->hasMainViewFrustum() && + (nodeData->getViewFrustumJustStoppedChanging() || + nodeData->hasLodChanged())); } if (nodeData->isPacketWaiting()) { @@ -445,7 +446,6 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) { _myServer->trackSend(dataID, dataEdited, _nodeUuid); }; - nodeData->copyCurrentViewFrustum(params.viewFrustum); bool somethingToSend = true; // assume we have something bool hadSomething = hasSomethingToSend(nodeData); diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index d242b393bf..eea8e8b470 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -294,7 +294,6 @@ void EntityScriptServer::run() { queryJSONParameters[EntityJSONQueryProperties::FLAGS_PROPERTY] = queryFlags; // setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter - _entityViewer.getOctreeQuery().setUsesFrustum(false); _entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters); entityScriptingInterface->setEntityTree(_entityViewer.getTree()); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd4562da54..d1d44aa706 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5791,14 +5791,8 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { ViewFrustum viewFrustum; copyViewFrustum(viewFrustum); - _octreeQuery.setCameraPosition(viewFrustum.getPosition()); - _octreeQuery.setCameraOrientation(viewFrustum.getOrientation()); - _octreeQuery.setCameraFov(viewFrustum.getFieldOfView()); - _octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio()); - _octreeQuery.setCameraNearClip(viewFrustum.getNearClip()); - _octreeQuery.setCameraFarClip(viewFrustum.getFarClip()); - _octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); - _octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius()); + _octreeQuery.setMainViewFrustum(viewFrustum); + auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 764c420197..11f37728df 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -37,15 +37,14 @@ void DiffTraversal::Waypoint::getNextVisibleElementFirstTime(DiffTraversal::Visi EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex); ++_nextIndex; if (nextElement) { - if (!view.usesViewFrustum) { + const auto& cube = nextElement->getAACube(); + if (!view.usesViewFrustums()) { // No LOD truncation if we aren't using the view frustum next.element = nextElement; return; - } else if (view.viewFrustum.cubeIntersectsKeyhole(nextElement->getAACube())) { + } else if (view.intersects(cube)) { // check for LOD truncation - float distance = glm::distance(view.viewFrustum.getPosition(), nextElement->getAACube().calcCenter()) + MIN_VISIBLE_DISTANCE; - float angularDiameter = nextElement->getAACube().getScale() / distance; - if (angularDiameter > MIN_ELEMENT_ANGULAR_DIAMETER * view.lodScaleFactor) { + if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) { next.element = nextElement; return; } @@ -76,17 +75,16 @@ void DiffTraversal::Waypoint::getNextVisibleElementRepeat( EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex); ++_nextIndex; if (nextElement && nextElement->getLastChanged() > lastTime) { - if (!view.usesViewFrustum) { + if (!view.usesViewFrustums()) { // No LOD truncation if we aren't using the view frustum next.element = nextElement; next.intersection = ViewFrustum::INSIDE; return; } else { // check for LOD truncation - float distance = glm::distance(view.viewFrustum.getPosition(), nextElement->getAACube().calcCenter()) + MIN_VISIBLE_DISTANCE; - float angularDiameter = nextElement->getAACube().getScale() / distance; - if (angularDiameter > MIN_ELEMENT_ANGULAR_DIAMETER * view.lodScaleFactor) { - ViewFrustum::intersection intersection = view.viewFrustum.calculateCubeKeyholeIntersection(nextElement->getAACube()); + const auto& cube = nextElement->getAACube(); + if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) { + ViewFrustum::intersection intersection = view.calculateIntersection(cube); if (intersection != ViewFrustum::OUTSIDE) { next.element = nextElement; next.intersection = intersection; @@ -118,14 +116,13 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex); ++_nextIndex; if (nextElement) { - AACube cube = nextElement->getAACube(); // check for LOD truncation - float distance = glm::distance(view.viewFrustum.getPosition(), cube.calcCenter()) + MIN_VISIBLE_DISTANCE; - float angularDiameter = cube.getScale() / distance; - if (angularDiameter > MIN_ELEMENT_ANGULAR_DIAMETER * view.lodScaleFactor) { - if (view.viewFrustum.calculateCubeKeyholeIntersection(cube) != ViewFrustum::OUTSIDE) { + const auto& cube = nextElement->getAACube(); + if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) { + ViewFrustum::intersection intersection = view.calculateIntersection(cube); + if (intersection != ViewFrustum::OUTSIDE) { next.element = nextElement; - next.intersection = ViewFrustum::OUTSIDE; + next.intersection = intersection; return; } } @@ -137,13 +134,83 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V next.intersection = ViewFrustum::OUTSIDE; } +bool DiffTraversal::View::isBigEnough(const AACube& cube, float minDiameter) const { + if (viewFrustums.empty()) { + // Everything is big enough when not using view frustums + return true; + } + + for (const auto& viewFrustum : viewFrustums) { + if (isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter)) { + return true; + } + } + return false; +} + +bool DiffTraversal::View::intersects(const AACube& cube) const { + if (viewFrustums.empty()) { + // Everything intersects when not using view frustums + return true; + } + + for (const auto& viewFrustum : viewFrustums) { + if (viewFrustum.cubeIntersectsKeyhole(cube)) { + return true; + } + } + return false; +} + +ViewFrustum::intersection DiffTraversal::View::calculateIntersection(const AACube& cube) const { + if (viewFrustums.empty()) { + // Everything is inside when not using view frustums + return ViewFrustum::INSIDE; + } + + ViewFrustum::intersection intersection = ViewFrustum::OUTSIDE; + + for (const auto& viewFrustum : viewFrustums) { + switch (viewFrustum.calculateCubeKeyholeIntersection(cube)) { + case ViewFrustum::INSIDE: + return ViewFrustum::INSIDE; + case ViewFrustum::INTERSECT: + intersection = ViewFrustum::INTERSECT; + break; + default: + // DO NOTHING + break; + } + } + return intersection; +} + +bool DiffTraversal::View::usesViewFrustums() const { + return !viewFrustums.empty(); +} + +bool DiffTraversal::View::isVerySimilar(const View& view) const { + auto size = view.viewFrustums.size(); + + if (view.lodScaleFactor != lodScaleFactor || + viewFrustums.size() != size) { + return false; + } + + for (size_t i = 0; i < size; ++i) { + if (!viewFrustums[i].isVerySimilar(view.viewFrustums[i])) { + return false; + } + } + return true; +} + DiffTraversal::DiffTraversal() { const int32_t MIN_PATH_DEPTH = 16; _path.reserve(MIN_PATH_DEPTH); } -DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, - int32_t lodLevelOffset, bool usesViewFrustum) { +DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) { assert(root); // there are three types of traversal: // @@ -155,33 +222,29 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr // // _getNextVisibleElementCallback = identifies elements that need to be traversed, // updates VisibleElement ref argument with pointer-to-element and view-intersection - // (INSIDE, INTERSECT, or OUTSIDE) + // (INSIDE, INTERSECtT, or OUTSIDE) // // external code should update the _scanElementCallback after calling prepareNewTraversal // - _currentView.usesViewFrustum = usesViewFrustum; - float lodScaleFactor = powf(2.0f, lodLevelOffset); Type type; // If usesViewFrustum changes, treat it as a First traversal - if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum) { + if (_completedView.startTime == 0 || _currentView.usesViewFrustums() != _completedView.usesViewFrustums()) { type = Type::First; - _currentView.viewFrustum = viewFrustum; - _currentView.lodScaleFactor = lodScaleFactor; + _currentView.viewFrustums = std::move(view.viewFrustums); + _currentView.lodScaleFactor = view.lodScaleFactor; _getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) { _path.back().getNextVisibleElementFirstTime(next, _currentView); }; - } else if (!_currentView.usesViewFrustum || - (_completedView.viewFrustum.isVerySimilar(viewFrustum) && - lodScaleFactor == _completedView.lodScaleFactor)) { + } else if (!_currentView.usesViewFrustums() || _completedView.isVerySimilar(view)) { type = Type::Repeat; _getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) { _path.back().getNextVisibleElementRepeat(next, _completedView, _completedView.startTime); }; } else { type = Type::Differential; - _currentView.viewFrustum = viewFrustum; - _currentView.lodScaleFactor = lodScaleFactor; + _currentView.viewFrustums = std::move(view.viewFrustums); + _currentView.lodScaleFactor = view.lodScaleFactor; _getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) { _path.back().getNextVisibleElementDifferential(next, _currentView, _completedView); }; diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index 69431d8db5..50fe74a75b 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -30,10 +30,15 @@ public: // View is a struct with a ViewFrustum and LOD parameters class View { public: - ViewFrustum viewFrustum; + bool isBigEnough(const AACube& cube, float minDiameter = MIN_ENTITY_ANGULAR_DIAMETER) const; + bool intersects(const AACube& cube) const; + bool usesViewFrustums() const; + bool isVerySimilar(const View& view) const; + ViewFrustum::intersection calculateIntersection(const AACube& cube) const; + + std::vector viewFrustums; uint64_t startTime { 0 }; float lodScaleFactor { 1.0f }; - bool usesViewFrustum { true }; }; // Waypoint is an bookmark in a "path" of waypoints during a traversal. @@ -57,15 +62,12 @@ public: DiffTraversal(); - Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum); + Type prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root); - const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; } - const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; } + const View& getCurrentView() const { return _currentView; } + const View& getCompletedView() const { return _completedView; } - bool doesCurrentUseViewFrustum() const { return _currentView.usesViewFrustum; } - float getCurrentLODScaleFactor() const { return _currentView.lodScaleFactor; } - float getCompletedLODScaleFactor() const { return _completedView.lodScaleFactor; } + bool doesCurrentUseViewFrustum() const { return _currentView.usesViewFrustums(); } uint64_t getStartOfCompletedTraversal() const { return _completedView.startTime; } bool finished() const { return _path.empty(); } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index a2ad834e18..b827ed7cd0 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -59,7 +59,6 @@ const int LOW_RES_MOVING_ADJUST = 1; class EncodeBitstreamParams { public: - ViewFrustum viewFrustum; bool includeExistsBits; NodeData* nodeData; diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 18766dd7f6..18e907cb8c 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeQuery.h" + #include #include @@ -16,23 +18,11 @@ #include #include -#include "OctreeConstants.h" -#include "OctreeQuery.h" - -const float DEFAULT_FOV = 45.0f; // degrees -const float DEFAULT_ASPECT_RATIO = 1.0f; -const float DEFAULT_NEAR_CLIP = 0.1f; -const float DEFAULT_FAR_CLIP = 3.0f; - -OctreeQuery::OctreeQuery(bool randomizeConnectionID) : - _cameraFov(DEFAULT_FOV), - _cameraAspectRatio(DEFAULT_ASPECT_RATIO), - _cameraNearClip(DEFAULT_NEAR_CLIP), - _cameraFarClip(DEFAULT_FAR_CLIP), - _cameraCenterRadius(DEFAULT_FAR_CLIP) -{ - _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; +using QueryFlags = uint8_t; +const QueryFlags QUERY_HAS_MAIN_FRUSTUM = 1U << 0; +const QueryFlags QUERY_HAS_SECONDARY_FRUSTUM = 1U << 1; +OctreeQuery::OctreeQuery(bool randomizeConnectionID) { if (randomizeConnectionID) { // randomize our initial octree query connection ID using random_device // the connection ID is 16 bits so we take a generated 32 bit value from random device and chop off the top @@ -47,26 +37,28 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { // pack the connection ID so the server can detect when we start a new connection memcpy(destinationBuffer, &_connectionID, sizeof(_connectionID)); destinationBuffer += sizeof(_connectionID); - - // back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum - memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum)); - destinationBuffer += sizeof(_usesFrustum); - - if (_usesFrustum) { - // TODO: DRY this up to a shared method - // that can pack any type given the number of bytes - // and return the number of bytes to push the pointer - - // camera details - memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); - destinationBuffer += sizeof(_cameraPosition); - destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); - memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); - destinationBuffer += sizeof(_cameraEyeOffsetPosition); + + // flags for wether the frustums are present + QueryFlags frustumFlags = 0; + if (_hasMainFrustum) { + frustumFlags |= QUERY_HAS_MAIN_FRUSTUM; + } + if (_hasSecondaryFrustum) { + frustumFlags |= QUERY_HAS_SECONDARY_FRUSTUM; + } + memcpy(destinationBuffer, &frustumFlags, sizeof(frustumFlags)); + destinationBuffer += sizeof(frustumFlags); + + if (_hasMainFrustum) { + auto byteArray = _mainViewFrustum.toByteArray(); + memcpy(destinationBuffer, byteArray.constData(), byteArray.size()); + destinationBuffer += byteArray.size(); + } + + if (_hasSecondaryFrustum) { + auto byteArray = _secondaryViewFrustum.toByteArray(); + memcpy(destinationBuffer, byteArray.constData(), byteArray.size()); + destinationBuffer += byteArray.size(); } // desired Max Octree PPS @@ -80,9 +72,6 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { // desired boundaryLevelAdjust memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust)); destinationBuffer += sizeof(_boundaryLevelAdjust); - - memcpy(destinationBuffer, &_cameraCenterRadius, sizeof(_cameraCenterRadius)); - destinationBuffer += sizeof(_cameraCenterRadius); // create a QByteArray that holds the binary representation of the JSON parameters QByteArray binaryParametersDocument; @@ -110,6 +99,7 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { int OctreeQuery::parseData(ReceivedMessage& message) { const unsigned char* startPosition = reinterpret_cast(message.getRawMessage()); + const unsigned char* endPosition = startPosition + message.getSize(); const unsigned char* sourceBuffer = startPosition; // unpack the connection ID @@ -133,20 +123,23 @@ int OctreeQuery::parseData(ReceivedMessage& message) { } // check if this query uses a view frustum - memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum)); - sourceBuffer += sizeof(_usesFrustum); - - if (_usesFrustum) { - // unpack camera details - memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition)); - sourceBuffer += sizeof(_cameraPosition); - sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation); - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov); - sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); - memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); - sourceBuffer += sizeof(_cameraEyeOffsetPosition); + QueryFlags frustumFlags { 0 }; + memcpy(&frustumFlags, sourceBuffer, sizeof(frustumFlags)); + sourceBuffer += sizeof(frustumFlags); + + _hasMainFrustum = frustumFlags & QUERY_HAS_MAIN_FRUSTUM; + _hasSecondaryFrustum = frustumFlags & QUERY_HAS_SECONDARY_FRUSTUM; + + if (_hasMainFrustum) { + auto bytesLeft = endPosition - sourceBuffer; + auto byteArray = QByteArray::fromRawData(reinterpret_cast(sourceBuffer), bytesLeft); + sourceBuffer += _mainViewFrustum.fromByteArray(byteArray); + } + + if (_hasSecondaryFrustum) { + auto bytesLeft = endPosition - sourceBuffer; + auto byteArray = QByteArray::fromRawData(reinterpret_cast(sourceBuffer), bytesLeft); + sourceBuffer += _secondaryViewFrustum.fromByteArray(byteArray); } // desired Max Octree PPS @@ -161,9 +154,6 @@ int OctreeQuery::parseData(ReceivedMessage& message) { memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust)); sourceBuffer += sizeof(_boundaryLevelAdjust); - memcpy(&_cameraCenterRadius, sourceBuffer, sizeof(_cameraCenterRadius)); - sourceBuffer += sizeof(_cameraCenterRadius); - // check if we have a packed JSON filter uint16_t binaryParametersBytes; memcpy(&binaryParametersBytes, sourceBuffer, sizeof(binaryParametersBytes)); @@ -184,8 +174,3 @@ int OctreeQuery::parseData(ReceivedMessage& message) { return sourceBuffer - startPosition; } - -glm::vec3 OctreeQuery::calculateCameraDirection() const { - glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FORWARD, 0.0f)); - return direction; -} diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index 21ce2e7fac..ef52e29f51 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -12,16 +12,14 @@ #ifndef hifi_OctreeQuery_h #define hifi_OctreeQuery_h -#include - -#include -#include - #include #include #include +#include + +#include "OctreeConstants.h" class OctreeQuery : public NodeData { Q_OBJECT @@ -30,31 +28,22 @@ public: OctreeQuery(bool randomizeConnectionID = false); virtual ~OctreeQuery() {} + OctreeQuery(const OctreeQuery&) = delete; + OctreeQuery& operator=(const OctreeQuery&) = delete; + int getBroadcastData(unsigned char* destinationBuffer); int parseData(ReceivedMessage& message) override; - // getters for camera details - const glm::vec3& getCameraPosition() const { return _cameraPosition; } - const glm::quat& getCameraOrientation() const { return _cameraOrientation; } - float getCameraFov() const { return _cameraFov; } - float getCameraAspectRatio() const { return _cameraAspectRatio; } - float getCameraNearClip() const { return _cameraNearClip; } - float getCameraFarClip() const { return _cameraFarClip; } - const glm::vec3& getCameraEyeOffsetPosition() const { return _cameraEyeOffsetPosition; } - float getCameraCenterRadius() const { return _cameraCenterRadius; } + bool hasMainViewFrustum() const { return _hasMainFrustum; } + void setMainViewFrustum(const ViewFrustum& viewFrustum) { _hasMainFrustum = true; _mainViewFrustum = viewFrustum; } + void clearMainViewFrustum() { _hasMainFrustum = false; } + const ViewFrustum& getMainViewFrustum() const { return _mainViewFrustum; } - glm::vec3 calculateCameraDirection() const; + bool hasSecondaryViewFrustum() const { return _hasSecondaryFrustum; } + void setSecondaryViewFrustum(const ViewFrustum& viewFrustum) { _hasSecondaryFrustum = true; _secondaryViewFrustum = viewFrustum; } + void clearSecondaryViewFrustum() { _hasSecondaryFrustum = false; } + const ViewFrustum& getSecondaryViewFrustum() const { return _secondaryViewFrustum; } - // setters for camera details - void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; } - void setCameraOrientation(const glm::quat& orientation) { _cameraOrientation = orientation; } - void setCameraFov(float fov) { _cameraFov = fov; } - void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; } - void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } - void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } - void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; } - void setCameraCenterRadius(float radius) { _cameraCenterRadius = radius; } - // getters/setters for JSON filter QJsonObject getJSONParameters() { QReadLocker locker { &_jsonParametersLock }; return _jsonParameters; } void setJSONParameters(const QJsonObject& jsonParameters) @@ -64,9 +53,6 @@ public: int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; } float getOctreeSizeScale() const { return _octreeElementSizeScale; } int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } - - bool getUsesFrustum() { return _usesFrustum; } - void setUsesFrustum(bool usesFrustum) { _usesFrustum = usesFrustum; } void incrementConnectionID() { ++_connectionID; } @@ -81,33 +67,22 @@ public slots: void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; } protected: - // camera details for the avatar - glm::vec3 _cameraPosition { glm::vec3(0.0f) }; - glm::quat _cameraOrientation { glm::quat() }; - float _cameraFov; - float _cameraAspectRatio; - float _cameraNearClip; - float _cameraFarClip; - float _cameraCenterRadius; - glm::vec3 _cameraEyeOffsetPosition { glm::vec3(0.0f) }; + bool _hasMainFrustum { false }; + ViewFrustum _mainViewFrustum; + bool _hasSecondaryFrustum { false }; + ViewFrustum _secondaryViewFrustum; // octree server sending items int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; float _octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE; /// used for LOD calculations int _boundaryLevelAdjust = 0; /// used for LOD calculations - - uint8_t _usesFrustum = true; + uint16_t _connectionID; // query connection ID, randomized to start, increments with each new connection to server QJsonObject _jsonParameters; QReadWriteLock _jsonParametersLock; bool _hasReceivedFirstQuery { false }; - -private: - // privatize the copy constructor and assignment operator so they cannot be called - OctreeQuery(const OctreeQuery&); - OctreeQuery& operator= (const OctreeQuery&); }; #endif // hifi_OctreeQuery_h diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index 16542b697e..d6e9343896 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -139,9 +139,14 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by } } -void OctreeQueryNode::copyCurrentViewFrustum(ViewFrustum& viewOut) const { +void OctreeQueryNode::copyCurrentMainViewFrustum(ViewFrustum& viewOut) const { QMutexLocker viewLocker(&_viewMutex); - viewOut = _currentViewFrustum; + viewOut = _currentMainViewFrustum; +} + +void OctreeQueryNode::copyCurrentSecondaryViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _currentSecondaryViewFrustum; } bool OctreeQueryNode::updateCurrentViewFrustum() { @@ -150,70 +155,50 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { return false; } - if (!_usesFrustum) { + if (!_hasMainFrustum && !_hasSecondaryFrustum) { // this client does not use a view frustum so the view frustum for this query has not changed return false; - } else { - bool currentViewFrustumChanged = false; - - ViewFrustum newestViewFrustum; - // get position and orientation details from the camera - newestViewFrustum.setPosition(getCameraPosition()); - newestViewFrustum.setOrientation(getCameraOrientation()); - - newestViewFrustum.setCenterRadius(getCameraCenterRadius()); - - // Also make sure it's got the correct lens details from the camera - float originalFOV = getCameraFov(); - float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; - - if (0.0f != getCameraAspectRatio() && - 0.0f != getCameraNearClip() && - 0.0f != getCameraFarClip() && - getCameraNearClip() != getCameraFarClip()) { - newestViewFrustum.setProjection(glm::perspective( - glm::radians(wideFOV), // hack - getCameraAspectRatio(), - getCameraNearClip(), - getCameraFarClip())); - newestViewFrustum.calculate(); - } - - - { // if there has been a change, then recalculate - QMutexLocker viewLocker(&_viewMutex); - if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { - _currentViewFrustum = newestViewFrustum; - currentViewFrustumChanged = true; - } - } - - // Also check for LOD changes from the client - if (_lodInitialized) { - if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) { - _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); - _lodChanged = true; - } - if (_lastClientOctreeSizeScale != getOctreeSizeScale()) { - _lastClientOctreeSizeScale = getOctreeSizeScale(); - _lodChanged = true; - } - } else { - _lodInitialized = true; - _lastClientOctreeSizeScale = getOctreeSizeScale(); - _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); - _lodChanged = false; - } - - // When we first detect that the view stopped changing, we record this. - // but we don't change it back to false until we've completely sent this - // scene. - if (_viewFrustumChanging && !currentViewFrustumChanged) { - _viewFrustumJustStoppedChanging = true; - } - _viewFrustumChanging = currentViewFrustumChanged; - return currentViewFrustumChanged; } + + bool currentViewFrustumChanged = false; + + { // if there has been a change, then recalculate + QMutexLocker viewLocker(&_viewMutex); + if (_hasMainFrustum && !_mainViewFrustum.isVerySimilar(_currentMainViewFrustum)) { + _currentMainViewFrustum = _mainViewFrustum; + currentViewFrustumChanged = true; + } + if (_hasSecondaryFrustum && !_secondaryViewFrustum.isVerySimilar(_currentSecondaryViewFrustum)) { + _currentSecondaryViewFrustum = _secondaryViewFrustum; + currentViewFrustumChanged = true; + } + } + + // Also check for LOD changes from the client + if (_lodInitialized) { + if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) { + _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); + _lodChanged = true; + } + if (_lastClientOctreeSizeScale != getOctreeSizeScale()) { + _lastClientOctreeSizeScale = getOctreeSizeScale(); + _lodChanged = true; + } + } else { + _lodInitialized = true; + _lastClientOctreeSizeScale = getOctreeSizeScale(); + _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust(); + _lodChanged = false; + } + + // When we first detect that the view stopped changing, we record this. + // but we don't change it back to false until we've completely sent this + // scene. + if (_viewFrustumChanging && !currentViewFrustumChanged) { + _viewFrustumJustStoppedChanging = true; + } + _viewFrustumChanging = currentViewFrustumChanged; + return currentViewFrustumChanged; } void OctreeQueryNode::setViewSent(bool viewSent) { diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h index 640a7c7ddc..d8f05c4043 100644 --- a/libraries/octree/src/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -49,7 +49,8 @@ public: OctreeElementExtraEncodeData extraEncodeData; - void copyCurrentViewFrustum(ViewFrustum& viewOut) const; + void copyCurrentMainViewFrustum(ViewFrustum& viewOut) const; + void copyCurrentSecondaryViewFrustum(ViewFrustum& viewOut) const; // These are not classic setters because they are calculating and maintaining state // which is set asynchronously through the network receive @@ -87,9 +88,6 @@ public: void setShouldForceFullScene(bool shouldForceFullScene) { _shouldForceFullScene = shouldForceFullScene; } private: - OctreeQueryNode(const OctreeQueryNode &); - OctreeQueryNode& operator= (const OctreeQueryNode&); - bool _viewSent { false }; std::unique_ptr _octreePacket; bool _octreePacketWaiting; @@ -99,7 +97,8 @@ private: quint64 _firstSuppressedPacket { usecTimestampNow() }; mutable QMutex _viewMutex { QMutex::Recursive }; - ViewFrustum _currentViewFrustum; + ViewFrustum _currentMainViewFrustum; + ViewFrustum _currentSecondaryViewFrustum; bool _viewFrustumChanging { false }; bool _viewFrustumJustStoppedChanging { true }; diff --git a/libraries/octree/src/OctreeUtils.cpp b/libraries/octree/src/OctreeUtils.cpp index 8980504431..8eaf22e198 100644 --- a/libraries/octree/src/OctreeUtils.cpp +++ b/libraries/octree/src/OctreeUtils.cpp @@ -16,6 +16,7 @@ #include #include +#include float calculateRenderAccuracy(const glm::vec3& position, const AABox& bounds, @@ -73,4 +74,10 @@ float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust // Smallest visible element is 1cm const float smallestSize = 0.01f; return (smallestSize * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale); -} \ No newline at end of file +} + +bool isAngularSizeBigEnough(glm::vec3 position, const AACube& cube, float lodScaleFactor, float minDiameter) { + float distance = glm::distance(cube.calcCenter(), position) + MIN_VISIBLE_DISTANCE; + float angularDiameter = cube.getScale() / distance; + return angularDiameter > minDiameter * lodScaleFactor; +} diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h index d5008376ea..58ab366d8d 100644 --- a/libraries/octree/src/OctreeUtils.h +++ b/libraries/octree/src/OctreeUtils.h @@ -15,6 +15,7 @@ #include "OctreeConstants.h" class AABox; +class AACube; class QJsonDocument; /// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple @@ -36,4 +37,6 @@ const float SQRT_THREE = 1.73205080f; const float MIN_ENTITY_ANGULAR_DIAMETER = MIN_ELEMENT_ANGULAR_DIAMETER * SQRT_THREE; const float MIN_VISIBLE_DISTANCE = 0.0001f; // helps avoid divide-by-zero check +bool isAngularSizeBigEnough(glm::vec3 position, const AACube& cube, float lodScaleFactor, float minDiameter); + #endif // hifi_OctreeUtils_h diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 2a2eebc0a7..f65f5407fd 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -134,7 +134,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const { return "Unknown"; } -void ViewFrustum::fromByteArray(const QByteArray& input) { +int ViewFrustum::fromByteArray(const QByteArray& input) { // From the wire! glm::vec3 cameraPosition; @@ -176,6 +176,8 @@ void ViewFrustum::fromByteArray(const QByteArray& input) { calculate(); } + + return sourceBuffer - startPosition; } diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 981aabe70c..70fcb4cc32 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -147,7 +147,7 @@ public: void invalidate(); // causes all reasonable intersection tests to fail QByteArray toByteArray(); - void fromByteArray(const QByteArray& input); + int fromByteArray(const QByteArray& input); private: glm::mat4 _view; From 98cf48694e8718887a2a6c1592d8e1171fe38ff2 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 16 Apr 2018 15:27:43 -0700 Subject: [PATCH 065/174] Expose secondary camera to game logic --- interface/src/Application.cpp | 32 ++++++++++++++++++++++++++++ interface/src/Application.h | 5 +++++ libraries/shared/src/ViewFrustum.cpp | 10 ++++----- libraries/shared/src/ViewFrustum.h | 1 + 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d1d44aa706..a38f4d022d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5532,6 +5532,26 @@ void Application::update(float deltaTime) { { QMutexLocker viewLocker(&_viewMutex); _myCamera.loadViewFrustum(_viewFrustum); + + + auto renderConfig = _renderEngine->getConfiguration(); + assert(renderConfig); + auto secondaryCamera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); + assert(secondaryCamera); + + if (secondaryCamera->isEnabled()) { + _secondaryViewFrustum.setPosition(secondaryCamera->position); + _secondaryViewFrustum.setOrientation(secondaryCamera->orientation); + _secondaryViewFrustum.setProjection(secondaryCamera->vFoV, + secondaryCamera->textureWidth / secondaryCamera->textureHeight, + secondaryCamera->nearClipPlaneDistance, + secondaryCamera->farClipPlaneDistance); + _secondaryViewFrustum.calculate(); + _hasSecondaryViewFrustum = true; + } else { + _hasSecondaryViewFrustum = false; + } + } quint64 now = usecTimestampNow(); @@ -5793,6 +5813,13 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { copyViewFrustum(viewFrustum); _octreeQuery.setMainViewFrustum(viewFrustum); + if (hasSecondaryViewFrustum()) { + copySecondaryViewFrustum(viewFrustum); + _octreeQuery.setSecondaryViewFrustum(viewFrustum); + } else { + _octreeQuery.clearSecondaryViewFrustum(); + } + auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); @@ -5876,6 +5903,11 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const { viewOut = _displayViewFrustum; } +void Application::copySecondaryViewFrustum(ViewFrustum& viewOut) const { + QMutexLocker viewLocker(&_viewMutex); + viewOut = _secondaryViewFrustum; +} + void Application::resetSensors(bool andReload) { DependencyManager::get()->reset(); DependencyManager::get()->reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 6d611bc8e2..043a9b52ab 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -178,6 +178,9 @@ public: // which might be different from the viewFrustum, i.e. shadowmap // passes, mirror window passes, etc void copyDisplayViewFrustum(ViewFrustum& viewOut) const; + void copySecondaryViewFrustum(ViewFrustum& viewOut) const; + bool hasSecondaryViewFrustum() const { return _hasSecondaryViewFrustum; } + const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } QSharedPointer getEntities() const { return DependencyManager::get(); } QUndoStack* getUndoStack() { return &_undoStack; } @@ -554,6 +557,8 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) ViewFrustum _displayViewFrustum; + ViewFrustum _secondaryViewFrustum; + bool _hasSecondaryViewFrustum; quint64 _lastQueriedTime; OctreeQuery _octreeQuery { true }; // NodeData derived class for querying octee cells from octree servers diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index f65f5407fd..c2b92aac5f 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -75,6 +75,10 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { _width = _corners[TOP_RIGHT_NEAR].x - _corners[TOP_LEFT_NEAR].x; } +void ViewFrustum::setProjection(float cameraFov, float cameraAspectRatio, float cameraNearClip, float cameraFarClip) { + setProjection(glm::perspective(glm::radians(cameraFov), cameraAspectRatio, cameraNearClip, cameraFarClip)); +} + // ViewFrustum::calculate() // // Description: this will calculate the view frustum bounds for a given position and direction @@ -168,12 +172,8 @@ int ViewFrustum::fromByteArray(const QByteArray& input) { 0.0f != cameraNearClip && 0.0f != cameraFarClip && cameraNearClip != cameraFarClip) { - setProjection(glm::perspective( - glm::radians(cameraFov), - cameraAspectRatio, - cameraNearClip, - cameraFarClip)); + setProjection(cameraFov, cameraAspectRatio, cameraNearClip, cameraFarClip); calculate(); } diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 70fcb4cc32..ba8957bba3 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -48,6 +48,7 @@ public: // setters for lens attributes void setProjection(const glm::mat4 & projection); + void setProjection(float cameraFov, float cameraAspectRatio, float cameraNearClip, float cameraFarClip); void setFocalLength(float focalLength) { _focalLength = focalLength; } bool isPerspective() const; From 7f67547faef1068a765f0aaba8b10a4a08060d12 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 16 Apr 2018 17:45:11 -0700 Subject: [PATCH 066/174] Update HeadlessViewer to not always send a frustum --- .../src/octree/OctreeHeadlessViewer.cpp | 13 +++------ .../src/octree/OctreeHeadlessViewer.h | 27 ++++++++----------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.cpp b/assignment-client/src/octree/OctreeHeadlessViewer.cpp index 4f022ae838..6d91a134c2 100644 --- a/assignment-client/src/octree/OctreeHeadlessViewer.cpp +++ b/assignment-client/src/octree/OctreeHeadlessViewer.cpp @@ -14,25 +14,18 @@ #include #include - -OctreeHeadlessViewer::OctreeHeadlessViewer() { - _viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); -} - void OctreeHeadlessViewer::queryOctree() { char serverType = getMyNodeType(); PacketType packetType = getMyQueryMessageType(); - _octreeQuery.setMainViewFrustum(_viewFrustum); - _octreeQuery.setOctreeSizeScale(_voxelSizeScale); - _octreeQuery.setBoundaryLevelAdjust(_boundaryLevelAdjust); + if (_hasViewFrustum) { + _octreeQuery.setMainViewFrustum(_viewFrustum); + } auto nodeList = DependencyManager::get(); auto node = nodeList->soloNodeOfType(serverType); if (node && node->getActiveSocket()) { - _octreeQuery.setMaxQueryPacketsPerSecond(getMaxPacketsPerSecond()); - auto queryPacket = NLPacket::create(packetType); // encode the query data diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.h b/assignment-client/src/octree/OctreeHeadlessViewer.h index feb8211c39..dea91ce66f 100644 --- a/assignment-client/src/octree/OctreeHeadlessViewer.h +++ b/assignment-client/src/octree/OctreeHeadlessViewer.h @@ -20,9 +20,6 @@ class OctreeHeadlessViewer : public OctreeProcessor { Q_OBJECT public: - OctreeHeadlessViewer(); - virtual ~OctreeHeadlessViewer() {}; - OctreeQuery& getOctreeQuery() { return _octreeQuery; } static int parseOctreeStats(QSharedPointer message, SharedNodePointer sourceNode); @@ -32,34 +29,32 @@ public slots: void queryOctree(); // setters for camera attributes - void setPosition(const glm::vec3& position) { _viewFrustum.setPosition(position); } - void setOrientation(const glm::quat& orientation) { _viewFrustum.setOrientation(orientation); } - void setCenterRadius(float radius) { _viewFrustum.setCenterRadius(radius); } - void setKeyholeRadius(float radius) { _viewFrustum.setCenterRadius(radius); } // TODO: remove this legacy support + void setPosition(const glm::vec3& position) { _hasViewFrustum = true; _viewFrustum.setPosition(position); } + void setOrientation(const glm::quat& orientation) { _hasViewFrustum = true; _viewFrustum.setOrientation(orientation); } + void setCenterRadius(float radius) { _hasViewFrustum = true; _viewFrustum.setCenterRadius(radius); } + void setKeyholeRadius(float radius) { _hasViewFrustum = true; _viewFrustum.setCenterRadius(radius); } // TODO: remove this legacy support // setters for LOD and PPS - void setVoxelSizeScale(float sizeScale) { _voxelSizeScale = sizeScale; } - void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; } - void setMaxPacketsPerSecond(int maxPacketsPerSecond) { _maxPacketsPerSecond = maxPacketsPerSecond; } + void setVoxelSizeScale(float sizeScale) { _octreeQuery.setOctreeSizeScale(sizeScale) ; } + void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _octreeQuery.setBoundaryLevelAdjust(boundaryLevelAdjust); } + void setMaxPacketsPerSecond(int maxPacketsPerSecond) { _octreeQuery.setMaxQueryPacketsPerSecond(maxPacketsPerSecond); } // getters for camera attributes const glm::vec3& getPosition() const { return _viewFrustum.getPosition(); } const glm::quat& getOrientation() const { return _viewFrustum.getOrientation(); } // getters for LOD and PPS - float getVoxelSizeScale() const { return _voxelSizeScale; } - int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } - int getMaxPacketsPerSecond() const { return _maxPacketsPerSecond; } + float getVoxelSizeScale() const { return _octreeQuery.getOctreeSizeScale(); } + int getBoundaryLevelAdjust() const { return _octreeQuery.getBoundaryLevelAdjust(); } + int getMaxPacketsPerSecond() const { return _octreeQuery.getMaxQueryPacketsPerSecond(); } unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); } private: OctreeQuery _octreeQuery; + bool _hasViewFrustum { false }; ViewFrustum _viewFrustum; - float _voxelSizeScale { DEFAULT_OCTREE_SIZE_SCALE }; - int _boundaryLevelAdjust { 0 }; - int _maxPacketsPerSecond { DEFAULT_MAX_OCTREE_PPS }; }; #endif // hifi_OctreeHeadlessViewer_h From 3862a02ceed3c1779761b039bd9f48dfb6ad11e6 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 16 Apr 2018 18:30:51 -0700 Subject: [PATCH 067/174] DRY traversal scan callbacks --- .../src/entities/EntityPriorityQueue.cpp | 4 + .../src/entities/EntityTreeSendThread.cpp | 218 ++++++++---------- libraries/entities/src/DiffTraversal.cpp | 29 ++- 3 files changed, 115 insertions(+), 136 deletions(-) diff --git a/assignment-client/src/entities/EntityPriorityQueue.cpp b/assignment-client/src/entities/EntityPriorityQueue.cpp index a38d537649..88dee58f9d 100644 --- a/assignment-client/src/entities/EntityPriorityQueue.cpp +++ b/assignment-client/src/entities/EntityPriorityQueue.cpp @@ -62,6 +62,10 @@ void ConicalView::set(const DiffTraversal::View& view) { } float ConicalView::computePriority(const AACube& cube) const { + if (_conicalViewFrustums.empty()) { + return PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; + } + float priority = PrioritizedEntity::DO_NOT_SEND; for (const auto& view : _conicalViewFrustums) { diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index d14d31bd09..a282c4ad4c 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -135,25 +135,27 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O bool forceRemove = prevSendQueue.top().shouldForceRemove(); prevSendQueue.pop(); if (entity) { - if (!forceRemove) { + float priority = PrioritizedEntity::DO_NOT_SEND; + + + if (forceRemove) { + priority = PrioritizedEntity::FORCE_REMOVE; + } else { bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { - if (_traversal.getCurrentView().intersects(cube)) { - float priority = _conicalView.computePriority(cube); - if (priority != PrioritizedEntity::DO_NOT_SEND) { - if (_traversal.getCurrentView().isBigEnough(cube)) { - _sendQueue.push(PrioritizedEntity(entity, priority)); - _entitiesInQueue.insert(entity.get()); - } - } + const auto& view = _traversal.getCurrentView(); + if (view.intersects(cube) && view.isBigEnough(cube)) { + priority = _conicalView.computePriority(cube); } } else { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); - _entitiesInQueue.insert(entity.get()); + priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } - } else { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::FORCE_REMOVE, true)); + } + + + if (priority != PrioritizedEntity::DO_NOT_SEND) { + _sendQueue.emplace(entity, priority, forceRemove); _entitiesInQueue.insert(entity.get()); } } @@ -245,104 +247,79 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En case DiffTraversal::First: // When we get to a First traversal, clear the _knownState _knownState.clear(); - if (view.usesViewFrustums()) { - _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { + _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { + next.element->forEachEntity([&](EntityItemPointer entity) { + // Bail early if we've already checked this entity this frame + if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { + return; + } + float priority = PrioritizedEntity::DO_NOT_SEND; + + + bool success = false; + AACube cube = entity->getQueryAACube(success); + if (success) { + const auto& view = _traversal.getCurrentView(); + // Check the size of the entity, it's possible that a "too small to see" entity is included in a + // larger octree cell because of its position (for example if it crosses the boundary of a cell it + // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen + // before we consider including it. + if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && + view.isBigEnough(cube)) { + priority = _conicalView.computePriority(cube); + } + } else { + priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; + } + + + if (priority != PrioritizedEntity::DO_NOT_SEND) { + _sendQueue.emplace(entity, priority); + _entitiesInQueue.insert(entity.get()); + } + }); + }); + break; + case DiffTraversal::Repeat: + _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { + uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal(); + if (next.element->getLastChangedContent() > startOfCompletedTraversal) { next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; } - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - if (_traversal.getCurrentView().intersects(cube)) { - // Check the size of the entity, it's possible that a "too small to see" entity is included in a - // larger octree cell because of its position (for example if it crosses the boundary of a cell it - // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen - // before we consider including it. - if (_traversal.getCurrentView().isBigEnough(cube)) { - float priority = _conicalView.computePriority(cube); - _sendQueue.push(PrioritizedEntity(entity, priority)); - _entitiesInQueue.insert(entity.get()); + float priority = PrioritizedEntity::DO_NOT_SEND; + + + auto knownTimestamp = _knownState.find(entity.get()); + if (knownTimestamp == _knownState.end()) { + bool success = false; + AACube cube = entity->getQueryAACube(success); + if (success) { + const auto& view = _traversal.getCurrentView(); + // See the DiffTraversal::First case for an explanation of the "entity is too small" check + if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && + view.isBigEnough(cube)) { + priority = _conicalView.computePriority(cube); } + } else { + priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } - } else { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); + } else if (entity->getLastEdited() > knownTimestamp->second) { + // it is known and it changed --> put it on the queue with any priority + // TODO: sort these correctly + priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; + } + + + if (priority != PrioritizedEntity::DO_NOT_SEND) { + _sendQueue.emplace(entity, priority); _entitiesInQueue.insert(entity.get()); } }); - }); - } else { - _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { - next.element->forEachEntity([&](EntityItemPointer entity) { - // Bail early if we've already checked this entity this frame - if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { - return; - } - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); - _entitiesInQueue.insert(entity.get()); - }); - }); - } - break; - case DiffTraversal::Repeat: - if (view.usesViewFrustums()) { - _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { - uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal(); - if (next.element->getLastChangedContent() > startOfCompletedTraversal) { - next.element->forEachEntity([&](EntityItemPointer entity) { - // Bail early if we've already checked this entity this frame - if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { - return; - } - auto knownTimestamp = _knownState.find(entity.get()); - if (knownTimestamp == _knownState.end()) { - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - if (next.intersection == ViewFrustum::INSIDE || - _traversal.getCurrentView().intersects(cube)) { - // See the DiffTraversal::First case for an explanation of the "entity is too small" check - if (_traversal.getCurrentView().isBigEnough(cube)) { - float priority = _conicalView.computePriority(cube); - _sendQueue.push(PrioritizedEntity(entity, priority)); - _entitiesInQueue.insert(entity.get()); - } - } - } else { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); - _entitiesInQueue.insert(entity.get()); - } - } else if (entity->getLastEdited() > knownTimestamp->second - || entity->getLastChangedOnServer() > knownTimestamp->second) { - // it is known and it changed --> put it on the queue with any priority - // TODO: sort these correctly - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); - _entitiesInQueue.insert(entity.get()); - } - }); - } - }); - } else { - _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { - uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal(); - if (next.element->getLastChangedContent() > startOfCompletedTraversal) { - next.element->forEachEntity([&](EntityItemPointer entity) { - // Bail early if we've already checked this entity this frame - if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { - return; - } - auto knownTimestamp = _knownState.find(entity.get()); - if (knownTimestamp == _knownState.end() - || entity->getLastEdited() > knownTimestamp->second - || entity->getLastChangedOnServer() > knownTimestamp->second) { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); - _entitiesInQueue.insert(entity.get()); - } - }); - } - }); - } + } + }); break; case DiffTraversal::Differential: assert(view.usesViewFrustums()); @@ -352,36 +329,35 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { return; } + float priority = PrioritizedEntity::DO_NOT_SEND; + + auto knownTimestamp = _knownState.find(entity.get()); if (knownTimestamp == _knownState.end()) { bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { - if (_traversal.getCurrentView().intersects(cube)) { - // See the DiffTraversal::First case for an explanation of the "entity is too small" check - if (_traversal.getCurrentView().isBigEnough(cube)) { - if (!_traversal.getCompletedView().intersects(cube)) { - float priority = _conicalView.computePriority(cube); - _sendQueue.push(PrioritizedEntity(entity, priority)); - _entitiesInQueue.insert(entity.get()); - } else if (!_traversal.getCompletedView().isBigEnough(cube)) { - // If this entity was skipped last time because it was too small, we still need to send it - // this object was skipped in last completed traversal - float priority = _conicalView.computePriority(cube); - _sendQueue.push(PrioritizedEntity(entity, priority)); - _entitiesInQueue.insert(entity.get()); - } - } + const auto& view = _traversal.getCurrentView(); + // See the DiffTraversal::First case for an explanation of the "entity is too small" check + if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && + view.isBigEnough(cube)) { + // If this entity wasn't in the last view or + // If this entity was skipped last time because it was too small, we still need to send it + priority = _conicalView.computePriority(cube); } } else { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); - _entitiesInQueue.insert(entity.get()); + priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } } else if (entity->getLastEdited() > knownTimestamp->second || entity->getLastChangedOnServer() > knownTimestamp->second) { // it is known and it changed --> put it on the queue with any priority // TODO: sort these correctly - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY)); + priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; + } + + + if (priority != PrioritizedEntity::DO_NOT_SEND) { + _sendQueue.emplace(entity, priority); _entitiesInQueue.insert(entity.get()); } }); @@ -499,11 +475,11 @@ void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) if (success) { // We can force a removal from _knownState if the current view is used and entity is out of view if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::FORCE_REMOVE, true)); + _sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true); _entitiesInQueue.insert(entity.get()); } } else { - _sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true)); + _sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true); _entitiesInQueue.insert(entity.get()); } } diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 11f37728df..d5f2273fd5 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -13,7 +13,6 @@ #include - DiffTraversal::Waypoint::Waypoint(EntityTreeElementPointer& element) : _nextIndex(0) { assert(element); _weakElement = element; @@ -140,12 +139,12 @@ bool DiffTraversal::View::isBigEnough(const AACube& cube, float minDiameter) con return true; } - for (const auto& viewFrustum : viewFrustums) { - if (isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter)) { - return true; - } - } - return false; + bool isBigEnough = std::any_of(std::begin(viewFrustums), std::end(viewFrustums), + [&](const ViewFrustum& viewFrustum) { + return isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter); + }); + + return isBigEnough; } bool DiffTraversal::View::intersects(const AACube& cube) const { @@ -154,12 +153,12 @@ bool DiffTraversal::View::intersects(const AACube& cube) const { return true; } - for (const auto& viewFrustum : viewFrustums) { - if (viewFrustum.cubeIntersectsKeyhole(cube)) { - return true; - } - } - return false; + bool intersects = std::any_of(std::begin(viewFrustums), std::end(viewFrustums), + [&](const ViewFrustum& viewFrustum) { + return viewFrustum.cubeIntersectsKeyhole(cube); + }); + + return intersects; } ViewFrustum::intersection DiffTraversal::View::calculateIntersection(const AACube& cube) const { @@ -231,7 +230,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View // If usesViewFrustum changes, treat it as a First traversal if (_completedView.startTime == 0 || _currentView.usesViewFrustums() != _completedView.usesViewFrustums()) { type = Type::First; - _currentView.viewFrustums = std::move(view.viewFrustums); + _currentView.viewFrustums = view.viewFrustums; _currentView.lodScaleFactor = view.lodScaleFactor; _getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) { _path.back().getNextVisibleElementFirstTime(next, _currentView); @@ -243,7 +242,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View }; } else { type = Type::Differential; - _currentView.viewFrustums = std::move(view.viewFrustums); + _currentView.viewFrustums = view.viewFrustums; _currentView.lodScaleFactor = view.lodScaleFactor; _getNextVisibleElementCallback = [this](DiffTraversal::VisibleElement& next) { _path.back().getNextVisibleElementDifferential(next, _currentView, _completedView); From 7a710093acc4abd982535985cd48ceed311380f0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Apr 2018 16:28:50 -0700 Subject: [PATCH 068/174] Fix build error --- libraries/entities/src/EntityTree.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 3289101967..d95dbf2990 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -27,9 +27,6 @@ using EntityTreePointer = std::shared_ptr; #include "MovingEntitiesOperator.h" class EntityEditFilters; -class Model; -using ModelPointer = std::shared_ptr; -using ModelWeakPointer = std::weak_ptr; class EntitySimulation; From 69a7f2d4aa2852ac43f4f5454beea494553c2925 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 17 Apr 2018 17:41:35 -0700 Subject: [PATCH 069/174] Fix entity server crash --- .../src/entities/EntityPriorityQueue.h | 47 ++++++++++++++++++- .../src/entities/EntityTreeSendThread.cpp | 22 ++++----- .../src/entities/EntityTreeSendThread.h | 1 - 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/assignment-client/src/entities/EntityPriorityQueue.h index 4068b4dc4b..730e08591e 100644 --- a/assignment-client/src/entities/EntityPriorityQueue.h +++ b/assignment-client/src/entities/EntityPriorityQueue.h @@ -13,6 +13,7 @@ #define hifi_EntityPriorityQueue_h #include +#include #include #include @@ -71,6 +72,50 @@ private: bool _forceRemove; }; -using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector, PrioritizedEntity::Compare >; +class EntityPriorityQueue { +public: + inline bool empty() const { + assert(_queue.empty() == _entities.empty()); + return _queue.empty(); + } + + inline const PrioritizedEntity& top() const { + assert(!_queue.empty()); + return _queue.top(); + } + + inline bool contains(const EntityItem* entity) const { + return _entities.find(entity) != std::end(_entities); + } + + inline void emplace(const EntityItemPointer& entity, float priority, bool forceRemove = false) { + assert(entity && !contains(entity.get())); + _queue.emplace(entity, priority, forceRemove); + _entities.insert(entity.get()); + assert(_queue.size() == _entities.size()); + } + + inline void pop() { + assert(!empty()); + _entities.erase(_queue.top().getRawEntityPointer()); + _queue.pop(); + assert(_queue.size() == _entities.size()); + } + + inline void swap(EntityPriorityQueue& other) { + std::swap(_queue, other._queue); + std::swap(_entities, other._entities); + } + +private: + using PriorityQueue = std::priority_queue, + PrioritizedEntity::Compare>; + + PriorityQueue _queue; + // Keep dictionary of al the entities in the queue for fast contain checks. + std::unordered_set _entities; + +}; #endif // hifi_EntityPriorityQueue_h diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index a282c4ad4c..ae7de01c3e 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -127,8 +127,9 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O // and also use the opportunity to cull anything no longer in view if (viewFrustumChanged && !_sendQueue.empty()) { EntityPriorityQueue prevSendQueue; - _sendQueue.swap(prevSendQueue); - _entitiesInQueue.clear(); + std::swap(_sendQueue, prevSendQueue); + assert(_sendQueue.empty()); + // Re-add elements from previous traversal if they still need to be sent while (!prevSendQueue.empty()) { EntityItemPointer entity = prevSendQueue.top().getEntity(); @@ -156,7 +157,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority, forceRemove); - _entitiesInQueue.insert(entity.get()); } } } @@ -250,7 +250,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En _traversal.setScanCallback([this](DiffTraversal::VisibleElement& next) { next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame - if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { + if (_sendQueue.contains(entity.get())) { return; } float priority = PrioritizedEntity::DO_NOT_SEND; @@ -275,7 +275,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority); - _entitiesInQueue.insert(entity.get()); } }); }); @@ -286,7 +285,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En if (next.element->getLastChangedContent() > startOfCompletedTraversal) { next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame - if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { + if (_sendQueue.contains(entity.get())) { return; } float priority = PrioritizedEntity::DO_NOT_SEND; @@ -315,7 +314,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority); - _entitiesInQueue.insert(entity.get()); } }); } @@ -326,7 +324,7 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En _traversal.setScanCallback([this] (DiffTraversal::VisibleElement& next) { next.element->forEachEntity([&](EntityItemPointer entity) { // Bail early if we've already checked this entity this frame - if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) { + if (_sendQueue.contains(entity.get())) { return; } float priority = PrioritizedEntity::DO_NOT_SEND; @@ -358,7 +356,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority); - _entitiesInQueue.insert(entity.get()); } }); }); @@ -447,11 +444,10 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream } } _sendQueue.pop(); - _entitiesInQueue.erase(entity.get()); } nodeData->stats.encodeStopped(); if (_sendQueue.empty()) { - assert(_entitiesInQueue.empty()); + assert(_sendQueue.empty()); params.stopReason = EncodeBitstreamParams::FINISHED; _extraEncodeData->entities.clear(); } @@ -469,18 +465,16 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) { if (entity) { - if (_entitiesInQueue.find(entity.get()) == _entitiesInQueue.end() && _knownState.find(entity.get()) != _knownState.end()) { + if (!_sendQueue.contains(entity.get()) && _knownState.find(entity.get()) != _knownState.end()) { bool success = false; AACube cube = entity->getQueryAACube(success); if (success) { // We can force a removal from _knownState if the current view is used and entity is out of view if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) { _sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true); - _entitiesInQueue.insert(entity.get()); } } else { _sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true); - _entitiesInQueue.insert(entity.get()); } } } diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 5ea723c8b2..9eea98b7fd 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -50,7 +50,6 @@ private: DiffTraversal _traversal; EntityPriorityQueue _sendQueue; - std::unordered_set _entitiesInQueue; std::unordered_map _knownState; ConicalView _conicalView; // cached optimized view for fast priority calculations From fea49744ed3acbc673eb1b160f526b6c9a898718 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 17 Apr 2018 18:15:47 -0700 Subject: [PATCH 070/174] Add comment for future work --- interface/src/Application.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a38f4d022d..ae84491097 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5534,6 +5534,9 @@ void Application::update(float deltaTime) { _myCamera.loadViewFrustum(_viewFrustum); + // TODO: Fix this by modeling the way the secondary camera works on how the main camera works + // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary + // camera should be. auto renderConfig = _renderEngine->getConfiguration(); assert(renderConfig); auto secondaryCamera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); From 4c90763236dcd83d66d7476fed57dfd25e48895c Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 18 Apr 2018 17:52:15 -0700 Subject: [PATCH 071/174] Correctly update secondary camera frustum --- interface/src/Application.cpp | 92 +++++++++++++++++++++++++++-------- interface/src/Application.h | 2 + 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae84491097..bbdae9218b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5179,6 +5179,78 @@ void Application::updateDialogs(float deltaTime) const { } } +void Application::updateSecondaryCameraViewFrustum() { + // TODO: Fix this by modeling the way the secondary camera works on how the main camera works + // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary + // camera should be. + + // Code based on SecondaryCameraJob + auto renderConfig = _renderEngine->getConfiguration(); + assert(renderConfig); + auto camera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); + assert(camera); + + if (!camera->isEnabled()) { + _hasSecondaryViewFrustum = false; + return; + } + + if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { + auto entityScriptingInterface = DependencyManager::get(); + auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); + glm::vec3 mirrorPropertiesPosition = entityProperties.getPosition(); + glm::quat mirrorPropertiesRotation = entityProperties.getRotation(); + glm::vec3 mirrorPropertiesDimensions = entityProperties.getDimensions(); + glm::vec3 halfMirrorPropertiesDimensions = 0.5f * mirrorPropertiesDimensions; + + // setup mirror from world as inverse of world from mirror transformation using inverted x and z for mirrored image + // TODO: we are assuming here that UP is world y-axis + glm::mat4 worldFromMirrorRotation = glm::mat4_cast(mirrorPropertiesRotation) * glm::scale(vec3(-1.0f, 1.0f, -1.0f)); + glm::mat4 worldFromMirrorTranslation = glm::translate(mirrorPropertiesPosition); + glm::mat4 worldFromMirror = worldFromMirrorTranslation * worldFromMirrorRotation; + glm::mat4 mirrorFromWorld = glm::inverse(worldFromMirror); + + // get mirror camera position by reflecting main camera position's z coordinate in mirror space + glm::vec3 mainCameraPositionWorld = getCamera().getPosition(); + glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f)); + glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, + -mainCameraPositionMirror.z); + glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f)); + + // set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation + glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation); + _secondaryViewFrustum.setPosition(mirrorCameraPositionWorld); + _secondaryViewFrustum.setOrientation(mirrorCameraOrientation); + + // build frustum using mirror space translation of mirrored camera + float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; + glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; + glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; + glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); + _secondaryViewFrustum.setProjection(frustum); + } else { + if (!camera->attachedEntityId.isNull()) { + auto entityScriptingInterface = DependencyManager::get(); + auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); + _secondaryViewFrustum.setPosition(entityProperties.getPosition()); + _secondaryViewFrustum.setOrientation(entityProperties.getRotation()); + } else { + _secondaryViewFrustum.setPosition(camera->position); + _secondaryViewFrustum.setOrientation(camera->orientation); + } + + float aspectRatio = (float)camera->textureWidth / (float)camera->textureHeight; + _secondaryViewFrustum.setProjection(camera->vFoV, + aspectRatio, + camera->nearClipPlaneDistance, + camera->farClipPlaneDistance); + } + // Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera, + // which is not what we want here. + _secondaryViewFrustum.calculate(); + _hasSecondaryViewFrustum = true; +} + static bool domainLoadingInProgress = false; void Application::update(float deltaTime) { @@ -5533,28 +5605,10 @@ void Application::update(float deltaTime) { QMutexLocker viewLocker(&_viewMutex); _myCamera.loadViewFrustum(_viewFrustum); - // TODO: Fix this by modeling the way the secondary camera works on how the main camera works // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary // camera should be. - auto renderConfig = _renderEngine->getConfiguration(); - assert(renderConfig); - auto secondaryCamera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); - assert(secondaryCamera); - - if (secondaryCamera->isEnabled()) { - _secondaryViewFrustum.setPosition(secondaryCamera->position); - _secondaryViewFrustum.setOrientation(secondaryCamera->orientation); - _secondaryViewFrustum.setProjection(secondaryCamera->vFoV, - secondaryCamera->textureWidth / secondaryCamera->textureHeight, - secondaryCamera->nearClipPlaneDistance, - secondaryCamera->farClipPlaneDistance); - _secondaryViewFrustum.calculate(); - _hasSecondaryViewFrustum = true; - } else { - _hasSecondaryViewFrustum = false; - } - + updateSecondaryCameraViewFrustum(); } quint64 now = usecTimestampNow(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 043a9b52ab..f31ca6547e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -149,6 +149,8 @@ public: void initializeRenderEngine(); void initializeUi(); + void updateSecondaryCameraViewFrustum(); + void updateCamera(RenderArgs& renderArgs, float deltaTime); void paintGL(); void resizeGL(); From 0820ef3c9582a89388090e3e929b3cd7a5010d8a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Apr 2018 20:19:27 -0700 Subject: [PATCH 072/174] Account for secondary view when deciding to query --- interface/src/Application.cpp | 3 +++ interface/src/Application.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bbdae9218b..a5b859628f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5622,6 +5622,8 @@ void Application::update(float deltaTime) { const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY; bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum); + viewIsDifferentEnough |= _hasSecondaryViewFrustum && !_lastQueriedSecondaryViewFrustum.isVerySimilar(_secondaryViewFrustum); + // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it if (queryIsDue || viewIsDifferentEnough) { _lastQueriedTime = now; @@ -5630,6 +5632,7 @@ void Application::update(float deltaTime) { } sendAvatarViewFrustum(); _lastQueriedViewFrustum = _viewFrustum; + _lastQueriedSecondaryViewFrustum = _secondaryViewFrustum; } } diff --git a/interface/src/Application.h b/interface/src/Application.h index f31ca6547e..eed6ceeae5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -557,9 +557,10 @@ private: mutable QMutex _viewMutex { QMutex::Recursive }; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. - ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) + ViewFrustum _lastQueriedViewFrustum; // last view frustum used to query octree servers ViewFrustum _displayViewFrustum; ViewFrustum _secondaryViewFrustum; + ViewFrustum _lastQueriedSecondaryViewFrustum; // last secondary view frustum used to query octree servers bool _hasSecondaryViewFrustum; quint64 _lastQueriedTime; From 30d14dcd45834c7241b67b3be63430399417f386 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 19 Apr 2018 13:23:24 -0700 Subject: [PATCH 073/174] Push packet version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 98b0e1d892..b16f9c903e 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -34,7 +34,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityPhysics: return static_cast(EntityVersion::MaterialData); case PacketType::EntityQuery: - return static_cast(EntityQueryPacketVersion::RemovedJurisdictions); + return static_cast(EntityQueryPacketVersion::MultiFrustumQuery); case PacketType::AvatarIdentity: case PacketType::AvatarData: case PacketType::BulkAvatarData: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index e6b133c158..9b48e3a132 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -244,7 +244,8 @@ enum class EntityQueryPacketVersion: PacketVersion { JSONFilter = 18, JSONFilterWithFamilyTree = 19, ConnectionIdentifier = 20, - RemovedJurisdictions = 21 + RemovedJurisdictions = 21, + MultiFrustumQuery = 22 }; enum class AssetServerPacketVersion: PacketVersion { From d47ddbd6e4f5a9e09425fb9b8c51e215e195672d Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 18:02:15 -0700 Subject: [PATCH 074/174] CR --- assignment-client/src/entities/EntityPriorityQueue.h | 5 +++-- .../src/entities/EntityTreeSendThread.cpp | 11 ++++------- libraries/entities/src/DiffTraversal.cpp | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/assignment-client/src/entities/EntityPriorityQueue.h index 730e08591e..9210ac549f 100644 --- a/assignment-client/src/entities/EntityPriorityQueue.h +++ b/assignment-client/src/entities/EntityPriorityQueue.h @@ -22,7 +22,7 @@ const float SQRT_TWO_OVER_TWO = 0.7071067811865f; const float DEFAULT_VIEW_RADIUS = 10.0f; -// ConicalView is an approximation of a ViewFrustum for fast calculation of sort priority. +// ConicalViewFrustum is an approximation of a ViewFrustum for fast calculation of sort priority. class ConicalViewFrustum { public: ConicalViewFrustum() {} @@ -37,6 +37,7 @@ private: float _radius { DEFAULT_VIEW_RADIUS }; }; +// Simple wrapper around a set of conical view frustums class ConicalView { public: ConicalView() {} @@ -113,7 +114,7 @@ private: PrioritizedEntity::Compare>; PriorityQueue _queue; - // Keep dictionary of al the entities in the queue for fast contain checks. + // Keep dictionary of all the entities in the queue for fast contain checks. std::unordered_set _entities; }; diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index ae7de01c3e..2e57f2e00f 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -138,7 +138,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O if (entity) { float priority = PrioritizedEntity::DO_NOT_SEND; - if (forceRemove) { priority = PrioritizedEntity::FORCE_REMOVE; } else { @@ -154,7 +153,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O } } - if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority, forceRemove); } @@ -305,7 +303,8 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En } else { priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } - } else if (entity->getLastEdited() > knownTimestamp->second) { + } else if (entity->getLastEdited() > knownTimestamp->second || + entity->getLastChangedOnServer() > knownTimestamp->second) { // it is known and it changed --> put it on the queue with any priority // TODO: sort these correctly priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; @@ -339,15 +338,13 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En // See the DiffTraversal::First case for an explanation of the "entity is too small" check if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && view.isBigEnough(cube)) { - // If this entity wasn't in the last view or - // If this entity was skipped last time because it was too small, we still need to send it priority = _conicalView.computePriority(cube); } } else { priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } - } else if (entity->getLastEdited() > knownTimestamp->second - || entity->getLastChangedOnServer() > knownTimestamp->second) { + } else if (entity->getLastEdited() > knownTimestamp->second || + entity->getLastChangedOnServer() > knownTimestamp->second) { // it is known and it changed --> put it on the queue with any priority // TODO: sort these correctly priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index d5f2273fd5..39328e11ad 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -221,7 +221,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View // // _getNextVisibleElementCallback = identifies elements that need to be traversed, // updates VisibleElement ref argument with pointer-to-element and view-intersection - // (INSIDE, INTERSECtT, or OUTSIDE) + // (INSIDE, INTERSECT, or OUTSIDE) // // external code should update the _scanElementCallback after calling prepareNewTraversal // From 21213e81f4bda569b8cca9db2088ec3375fe1d71 Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 18 Apr 2018 16:21:03 -0700 Subject: [PATCH 075/174] Multiview support for priority queue --- .../src/avatars/AvatarMixerSlave.cpp | 2 +- interface/src/Application.h | 6 ++-- interface/src/avatar/AvatarManager.cpp | 16 +++++++-- .../src/EntityTreeRenderer.cpp | 20 ++++++++--- .../src/EntityTreeRenderer.h | 3 +- .../src/AbstractViewStateInterface.h | 4 +++ libraries/shared/src/PrioritySortUtil.h | 33 ++++++++++++------- tests/render-perf/src/main.cpp | 10 ++++++ 8 files changed, 71 insertions(+), 23 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 6f19b73cc5..da9b7934ad 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -223,7 +223,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) // prepare to sort ViewFrustum cameraView = nodeData->getViewFrustum(); - PrioritySortUtil::PriorityQueue sortedAvatars(cameraView, + PrioritySortUtil::PriorityQueue sortedAvatars({cameraView}, AvatarData::_avatarSortCoefficientSize, AvatarData::_avatarSortCoefficientCenter, AvatarData::_avatarSortCoefficientAge); diff --git a/interface/src/Application.h b/interface/src/Application.h index eed6ceeae5..256f428d12 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -175,13 +175,13 @@ public: Camera& getCamera() { return _myCamera; } const Camera& getCamera() const { return _myCamera; } // Represents the current view frustum of the avatar. - void copyViewFrustum(ViewFrustum& viewOut) const; + void copyViewFrustum(ViewFrustum& viewOut) const override; + void copySecondaryViewFrustum(ViewFrustum& viewOut) const override; + bool hasSecondaryViewFrustum() const override { return _hasSecondaryViewFrustum; } // Represents the view frustum of the current rendering pass, // which might be different from the viewFrustum, i.e. shadowmap // passes, mirror window passes, etc void copyDisplayViewFrustum(ViewFrustum& viewOut) const; - void copySecondaryViewFrustum(ViewFrustum& viewOut) const; - bool hasSecondaryViewFrustum() const { return _hasSecondaryViewFrustum; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } QSharedPointer getEntities() const { return DependencyManager::get(); } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index b71c060465..cd20fd9350 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -155,9 +155,19 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { AvatarSharedPointer _avatar; }; - ViewFrustum cameraView; - qApp->copyDisplayViewFrustum(cameraView); - PrioritySortUtil::PriorityQueue sortedAvatars(cameraView, + + std::vector views; + + ViewFrustum view; + qApp->copyCurrentViewFrustum(view); + views.push_back(view); + + if (qApp->hasSecondaryViewFrustum()) { + qApp->copySecondaryViewFrustum(view); + views.push_back(view); + } + + PrioritySortUtil::PriorityQueue sortedAvatars(views, AvatarData::_avatarSortCoefficientSize, AvatarData::_avatarSortCoefficientCenter, AvatarData::_avatarSortCoefficientAge); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ba81922979..511fa33591 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -296,7 +296,8 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } } -void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction) { +void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const std::vector& views, + render::Transaction& transaction) { PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size()); PerformanceTimer pt("change"); std::unordered_set changedEntities; @@ -357,7 +358,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene // prioritize and sort the renderables uint64_t sortStart = usecTimestampNow(); - PrioritySortUtil::PriorityQueue sortedRenderables(view); + PrioritySortUtil::PriorityQueue sortedRenderables(views); { PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); std::unordered_map::iterator itr = _renderablesToUpdate.begin(); @@ -415,9 +416,20 @@ void EntityTreeRenderer::update(bool simulate) { if (scene) { render::Transaction transaction; addPendingEntities(scene, transaction); + + std::vector views; + ViewFrustum view; - _viewState->copyCurrentViewFrustum(view); - updateChangedEntities(scene, view, transaction); + _viewState->copyViewFrustum(view); + views.push_back(view); + + if (_viewState->hasSecondaryViewFrustum()) { + _viewState->copySecondaryViewFrustum(view); + views.push_back(view); + } + + + updateChangedEntities(scene, views, transaction); scene->enqueueTransaction(transaction); } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index f5cedfdd01..7a7920d5b2 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -148,7 +148,8 @@ protected: private: void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction); - void updateChangedEntities(const render::ScenePointer& scene, const ViewFrustum& view, render::Transaction& transaction); + void updateChangedEntities(const render::ScenePointer& scene, const std::vector& views, + render::Transaction& transaction); EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); } render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); } diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 54fdc903ca..9d781b7d18 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -31,6 +31,10 @@ public: /// copies the current view frustum for rendering the view state virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0; + virtual void copyViewFrustum(ViewFrustum& viewOut) const = 0; + virtual void copySecondaryViewFrustum(ViewFrustum& viewOut) const = 0; + virtual bool hasSecondaryViewFrustum() const = 0; + virtual QThread* getMainThread() = 0; virtual PickRay computePickRay(float x, float y) const = 0; diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index 279fa42ea4..7c0f30ec75 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -83,15 +83,15 @@ namespace PrioritySortUtil { template class PriorityQueue { public: + using Views = std::vector; + PriorityQueue() = delete; - - PriorityQueue(const ViewFrustum& view) : _view(view) { } - - PriorityQueue(const ViewFrustum& view, float angularWeight, float centerWeight, float ageWeight) - : _view(view), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight) + PriorityQueue(const Views& views) : _views(views) { } + PriorityQueue(const Views& views, float angularWeight, float centerWeight, float ageWeight) + : _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight) { } - void setView(const ViewFrustum& view) { _view = view; } + void setViews(const Views& views) { _views = views; } void setWeights(float angularWeight, float centerWeight, float ageWeight) { _angularWeight = angularWeight; @@ -109,7 +109,18 @@ namespace PrioritySortUtil { bool empty() const { return _queue.empty(); } private: + float computePriority(const T& thing) const { + float priority = std::numeric_limits::min(); + + for (const auto& view : _views) { + priority = std::max(priority, computePriority(view, thing)); + } + + return priority; + } + + float computePriority(const ViewFrustum& view, const T& thing) const { // priority = weighted linear combination of multiple values: // (a) angular size // (b) proximity to center of view @@ -117,11 +128,11 @@ namespace PrioritySortUtil { // where the relative "weights" are tuned to scale the contributing values into units of "priority". glm::vec3 position = thing.getPosition(); - glm::vec3 offset = position - _view.getPosition(); + glm::vec3 offset = position - view.getPosition(); float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero const float MIN_RADIUS = 0.1f; // WORKAROUND for zero size objects (we still want them to sort by distance) float radius = glm::min(thing.getRadius(), MIN_RADIUS); - float cosineAngle = (glm::dot(offset, _view.getDirection()) / distance); + float cosineAngle = (glm::dot(offset, view.getDirection()) / distance); float age = (float)(usecTimestampNow() - thing.getTimestamp()); // we modulatate "age" drift rate by the cosineAngle term to make periphrial objects sort forward @@ -134,8 +145,8 @@ namespace PrioritySortUtil { + _ageWeight * cosineAngleFactor * age; // decrement priority of things outside keyhole - if (distance - radius > _view.getCenterRadius()) { - if (!_view.sphereIntersectsFrustum(position, radius)) { + if (distance - radius > view.getCenterRadius()) { + if (!view.sphereIntersectsFrustum(position, radius)) { constexpr float OUT_OF_VIEW_PENALTY = -10.0f; priority += OUT_OF_VIEW_PENALTY; } @@ -143,7 +154,7 @@ namespace PrioritySortUtil { return priority; } - ViewFrustum _view; + Views _views; std::priority_queue _queue; float _angularWeight { DEFAULT_ANGULAR_COEF }; float _centerWeight { DEFAULT_CENTER_COEF }; diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 9249b3d957..8c17d7c5c2 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -441,6 +441,16 @@ protected: viewOut = _viewFrustum; } + void copyViewFrustum(ViewFrustum& viewOut) const override { + viewOut = _viewFrustum; + } + + void copySecondaryViewFrustum(ViewFrustum& viewOut) const override {} + + bool hasSecondaryViewFrustum() const override { + return false; + } + QThread* getMainThread() override { return QThread::currentThread(); } From 1b2b70b7691b65cfa96881cddd005a6f2d664147 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 23 Apr 2018 15:47:05 -0700 Subject: [PATCH 076/174] Send both frustums to Avatar Mixer --- assignment-client/src/avatars/AvatarMixer.cpp | 8 +++----- .../src/avatars/AvatarMixerClientData.cpp | 16 ++++++++++++---- .../src/avatars/AvatarMixerClientData.h | 4 ++-- .../src/avatars/AvatarMixerSlave.cpp | 4 ++-- interface/src/Application.cpp | 4 ++++ 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 29340f6474..6353a1664f 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -521,11 +521,9 @@ void AvatarMixer::handleViewFrustumPacket(QSharedPointer messag auto start = usecTimestampNow(); getOrCreateClientData(senderNode); - if (senderNode->getLinkedData()) { - AvatarMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData()); - if (nodeData != nullptr) { - nodeData->readViewFrustumPacket(message->getMessage()); - } + AvatarMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData()); + if (nodeData) { + nodeData->readViewFrustumPacket(message->getMessage()); } auto end = usecTimestampNow(); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 268aba62d6..8c159cf744 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -19,8 +19,6 @@ AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID) : NodeData(nodeID) { - _currentViewFrustum.invalidate(); - // in case somebody calls getSessionUUID on the AvatarData instance, make sure it has the right ID _avatar->setID(nodeID); } @@ -129,11 +127,21 @@ void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, } void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) { - _currentViewFrustum.fromByteArray(message); + _currentViewFrustums.clear(); + + auto offset = 0; + while (offset < message.size()) { + ViewFrustum frustum; + offset += frustum.fromByteArray(message); + _currentViewFrustums.push_back(frustum); + } } bool AvatarMixerClientData::otherAvatarInView(const AABox& otherAvatarBox) { - return _currentViewFrustum.boxIntersectsKeyhole(otherAvatarBox); + return std::any_of(std::begin(_currentViewFrustums), std::end(_currentViewFrustums), + [&](const ViewFrustum& viewFrustum) { + return viewFrustum.boxIntersectsKeyhole(otherAvatarBox); + }); } void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const { diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 6963f4df0d..4b06617175 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -110,7 +110,7 @@ public: bool getRequestsDomainListData() { return _requestsDomainListData; } void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; } - ViewFrustum getViewFrustum() const { return _currentViewFrustum; } + const std::vector& getViewFrustums() const { return _currentViewFrustums; } uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const; void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time); @@ -150,7 +150,7 @@ private: SimpleMovingAverage _avgOtherAvatarDataRate; std::unordered_set _radiusIgnoredOthers; - ViewFrustum _currentViewFrustum; + std::vector _currentViewFrustums; int _recentOtherAvatarsInView { 0 }; int _recentOtherAvatarsOutOfView { 0 }; diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index da9b7934ad..30d94ed772 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -222,8 +222,8 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) }; // prepare to sort - ViewFrustum cameraView = nodeData->getViewFrustum(); - PrioritySortUtil::PriorityQueue sortedAvatars({cameraView}, + const auto& cameraViews = nodeData->getViewFrustums(); + PrioritySortUtil::PriorityQueue sortedAvatars(cameraViews, AvatarData::_avatarSortCoefficientSize, AvatarData::_avatarSortCoefficientCenter, AvatarData::_avatarSortCoefficientAge); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a5b859628f..33c334b493 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5806,6 +5806,10 @@ void Application::update(float deltaTime) { void Application::sendAvatarViewFrustum() { QByteArray viewFrustumByteArray = _viewFrustum.toByteArray(); + if (hasSecondaryViewFrustum()) { + viewFrustumByteArray += _viewFrustum.toByteArray(); + } + auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size()); avatarPacket->write(viewFrustumByteArray); From 538f24162f3ecc2892ca361a0339eced1087113f Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 23 Apr 2018 15:57:21 -0700 Subject: [PATCH 077/174] Define ViewFrustums type alias --- assignment-client/src/avatars/AvatarMixerClientData.h | 4 ++-- interface/src/avatar/AvatarManager.cpp | 2 +- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- libraries/entities-renderer/src/EntityTreeRenderer.h | 2 +- libraries/entities/src/DiffTraversal.h | 2 +- libraries/shared/src/PrioritySortUtil.h | 10 ++++------ libraries/shared/src/ViewFrustum.h | 1 + 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 4b06617175..13415d6a66 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -110,7 +110,7 @@ public: bool getRequestsDomainListData() { return _requestsDomainListData; } void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; } - const std::vector& getViewFrustums() const { return _currentViewFrustums; } + const ViewFrustums& getViewFrustums() const { return _currentViewFrustums; } uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const; void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time); @@ -150,7 +150,7 @@ private: SimpleMovingAverage _avgOtherAvatarDataRate; std::unordered_set _radiusIgnoredOthers; - std::vector _currentViewFrustums; + ViewFrustums _currentViewFrustums; int _recentOtherAvatarsInView { 0 }; int _recentOtherAvatarsOutOfView { 0 }; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index cd20fd9350..087e23a933 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -156,7 +156,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { }; - std::vector views; + ViewFrustums views; ViewFrustum view; qApp->copyCurrentViewFrustum(view); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 511fa33591..6dd13c7332 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -296,7 +296,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } } -void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const std::vector& views, +void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustums& views, render::Transaction& transaction) { PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size()); PerformanceTimer pt("change"); @@ -417,7 +417,7 @@ void EntityTreeRenderer::update(bool simulate) { render::Transaction transaction; addPendingEntities(scene, transaction); - std::vector views; + ViewFrustums views; ViewFrustum view; _viewState->copyViewFrustum(view); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 7a7920d5b2..9ed4f9d21d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -148,7 +148,7 @@ protected: private: void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction); - void updateChangedEntities(const render::ScenePointer& scene, const std::vector& views, + void updateChangedEntities(const render::ScenePointer& scene, const ViewFrustums& views, render::Transaction& transaction); EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); } render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); } diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index 50fe74a75b..0fd014ac23 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -36,7 +36,7 @@ public: bool isVerySimilar(const View& view) const; ViewFrustum::intersection calculateIntersection(const AACube& cube) const; - std::vector viewFrustums; + ViewFrustums viewFrustums; uint64_t startTime { 0 }; float lodScaleFactor { 1.0f }; }; diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index 7c0f30ec75..ba15222611 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -83,15 +83,13 @@ namespace PrioritySortUtil { template class PriorityQueue { public: - using Views = std::vector; - PriorityQueue() = delete; - PriorityQueue(const Views& views) : _views(views) { } - PriorityQueue(const Views& views, float angularWeight, float centerWeight, float ageWeight) + PriorityQueue(const ViewFrustums& views) : _views(views) { } + PriorityQueue(const ViewFrustums& views, float angularWeight, float centerWeight, float ageWeight) : _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight) { } - void setViews(const Views& views) { _views = views; } + void setViews(const ViewFrustums& views) { _views = views; } void setWeights(float angularWeight, float centerWeight, float ageWeight) { _angularWeight = angularWeight; @@ -154,7 +152,7 @@ namespace PrioritySortUtil { return priority; } - Views _views; + ViewFrustums _views; std::priority_queue _queue; float _angularWeight { DEFAULT_ANGULAR_COEF }; float _centerWeight { DEFAULT_CENTER_COEF }; diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index ba8957bba3..128a717df8 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -189,5 +189,6 @@ private: }; using ViewFrustumPointer = std::shared_ptr; +using ViewFrustums = std::vector; #endif // hifi_ViewFrustum_h From ddde0228ba3b1fd6b8a3006101594ff6ead9e2a8 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 23 Apr 2018 16:10:44 -0700 Subject: [PATCH 078/174] Fix AC not sending Avatar Mixer a frustum --- assignment-client/src/Agent.cpp | 15 +++++++++++++++ assignment-client/src/Agent.h | 1 + interface/src/Application.cpp | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 1df901dd98..26bfb586a6 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -594,9 +594,24 @@ void Agent::sendAvatarIdentityPacket() { auto scriptedAvatar = DependencyManager::get(); scriptedAvatar->markIdentityDataChanged(); scriptedAvatar->sendIdentityPacket(); + sendAvatarViewFrustum(); } } +void Agent::sendAvatarViewFrustum() { + auto scriptedAvatar = DependencyManager::get(); + ViewFrustum view; + view.setPosition(scriptedAvatar->getWorldPosition()); + view.setOrientation(scriptedAvatar->getHeadOrientation()); + auto viewFrustumByteArray = view.toByteArray(); + + auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size()); + avatarPacket->write(viewFrustumByteArray); + + DependencyManager::get()->broadcastToNodes(std::move(avatarPacket), + { NodeType::AvatarMixer }); +} + void Agent::processAgentAvatar() { if (!_scriptEngine->isFinished() && _isAvatar) { auto scriptedAvatar = DependencyManager::get(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 1229f06276..e4ce0f95eb 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -97,6 +97,7 @@ private: void setAvatarSound(SharedSoundPointer avatarSound) { _avatarSound = avatarSound; } void sendAvatarIdentityPacket(); + void sendAvatarViewFrustum(); QString _scriptContents; QTimer* _scriptRequestTimeout { nullptr }; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 33c334b493..cdb535fad1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5806,8 +5806,8 @@ void Application::update(float deltaTime) { void Application::sendAvatarViewFrustum() { QByteArray viewFrustumByteArray = _viewFrustum.toByteArray(); - if (hasSecondaryViewFrustum()) { - viewFrustumByteArray += _viewFrustum.toByteArray(); + if (_hasSecondaryViewFrustum) { + viewFrustumByteArray += _secondaryViewFrustum.toByteArray(); } auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size()); From a283d28686fcdb9aa138dad0d66e4d4ab5ccb2b4 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 24 Apr 2018 19:09:16 -0700 Subject: [PATCH 079/174] Send number of frustums in packet --- assignment-client/src/Agent.cpp | 7 ++++++- .../src/avatars/AvatarMixerClientData.cpp | 13 +++++++++---- .../src/avatars/AvatarMixerClientData.h | 2 +- interface/src/Application.cpp | 6 +++++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 26bfb586a6..8816ed9629 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -600,12 +600,17 @@ void Agent::sendAvatarIdentityPacket() { void Agent::sendAvatarViewFrustum() { auto scriptedAvatar = DependencyManager::get(); + ViewFrustum view; view.setPosition(scriptedAvatar->getWorldPosition()); view.setOrientation(scriptedAvatar->getHeadOrientation()); + view.calculate(); + + uint8_t numFrustums = 1; auto viewFrustumByteArray = view.toByteArray(); - auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size()); + auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size() + sizeof(numFrustums)); + avatarPacket->writePrimitive(numFrustums); avatarPacket->write(viewFrustumByteArray); DependencyManager::get()->broadcastToNodes(std::move(avatarPacket), diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 8c159cf744..a8e5a7c541 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -126,13 +126,18 @@ void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, } } -void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) { +void AvatarMixerClientData::readViewFrustumPacket(QByteArray message) { _currentViewFrustums.clear(); + + uint8_t numFrustums = 0; + memcpy(&numFrustums, message.constData(), sizeof(numFrustums)); + message.remove(0, sizeof(numFrustums)); - auto offset = 0; - while (offset < message.size()) { + for (uint8_t i = 0; i < numFrustums; ++i) { ViewFrustum frustum; - offset += frustum.fromByteArray(message); + auto bytesRead = frustum.fromByteArray(message); + message.remove(0, bytesRead); + _currentViewFrustums.push_back(frustum); } } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 13415d6a66..f17404b79f 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -98,7 +98,7 @@ public: void removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other); void ignoreOther(SharedNodePointer self, SharedNodePointer other); - void readViewFrustumPacket(const QByteArray& message); + void readViewFrustumPacket(QByteArray message); bool otherAvatarInView(const AABox& otherAvatarBox); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cdb535fad1..c88b5981b4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5805,12 +5805,16 @@ void Application::update(float deltaTime) { } void Application::sendAvatarViewFrustum() { + uint8_t numFrustums = 1; QByteArray viewFrustumByteArray = _viewFrustum.toByteArray(); + if (_hasSecondaryViewFrustum) { + ++numFrustums; viewFrustumByteArray += _secondaryViewFrustum.toByteArray(); } - auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size()); + auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size() + sizeof(numFrustums)); + avatarPacket->writePrimitive(numFrustums); avatarPacket->write(viewFrustumByteArray); DependencyManager::get()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer); From 2ad948c46219e75bbfab174aea2aeb4674adadb7 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 24 Apr 2018 19:12:42 -0700 Subject: [PATCH 080/174] Bump ViewFrustum packet version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 ++ libraries/networking/src/udt/PacketHeaders.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index b16f9c903e..17b0d90cfe 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -90,6 +90,8 @@ PacketVersion versionForPacketType(PacketType packetType) { return 18; // replace min_avatar_scale and max_avatar_scale with min_avatar_height and max_avatar_height case PacketType::Ping: return static_cast(PingVersion::IncludeConnectionID); + case PacketType::ViewFrustum: + return static_cast(ViewFrustumVersion::SendMultipleFrustums); default: return 20; } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 9b48e3a132..c72bbb0129 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -328,4 +328,8 @@ enum class PingVersion : PacketVersion { IncludeConnectionID = 18 }; +enum class ViewFrustumVersion : PacketVersion { + SendMultipleFrustums = 21 +}; + #endif // hifi_PacketHeaders_h From 83a438eb22c02ea6a86301433588c119d023a1f3 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 18:10:55 -0700 Subject: [PATCH 081/174] Set avatar view packets on their own timer --- assignment-client/src/Agent.cpp | 10 ++++++++-- assignment-client/src/Agent.h | 1 + libraries/avatars/src/AvatarData.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 8816ed9629..f560ea72bd 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -548,16 +548,18 @@ void Agent::setIsAvatar(bool isAvatar) { if (_isAvatar && !_avatarIdentityTimer) { // set up the avatar timers _avatarIdentityTimer = new QTimer(this); + _avatarViewTimer = new QTimer(this); // connect our slot connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket); + connect(_avatarViewTimer, &QTimer::timeout, this, &Agent::sendAvatarViewFrustum); // start the timers _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets + _avatarViewTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS); // tell the avatarAudioTimer to start ticking QMetaObject::invokeMethod(&_avatarAudioTimer, "start"); - } if (!_isAvatar) { @@ -567,6 +569,10 @@ void Agent::setIsAvatar(bool isAvatar) { delete _avatarIdentityTimer; _avatarIdentityTimer = nullptr; + _avatarViewTimer->stop(); + delete _avatarViewTimer; + _avatarViewTimer = nullptr; + // The avatar mixer never times out a connection (e.g., based on identity or data packets) // but rather keeps avatars in its list as long as "connected". As a result, clients timeout // when we stop sending identity, but then get woken up again by the mixer itself, which sends @@ -585,6 +591,7 @@ void Agent::setIsAvatar(bool isAvatar) { nodeList->sendPacket(std::move(packet), *node); }); } + QMetaObject::invokeMethod(&_avatarAudioTimer, "stop"); } } @@ -594,7 +601,6 @@ void Agent::sendAvatarIdentityPacket() { auto scriptedAvatar = DependencyManager::get(); scriptedAvatar->markIdentityDataChanged(); scriptedAvatar->sendIdentityPacket(); - sendAvatarViewFrustum(); } } diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index e4ce0f95eb..d144f0bc01 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -107,6 +107,7 @@ private: int _numAvatarSoundSentBytes = 0; bool _isAvatar = false; QTimer* _avatarIdentityTimer = nullptr; + QTimer* _avatarViewTimer = nullptr; QHash _outgoingScriptAudioSequenceNumbers; AudioGate _audioGate; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 888c3bfb24..3db94f6691 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -278,6 +278,7 @@ namespace AvatarDataPacket { const float MAX_AUDIO_LOUDNESS = 1000.0f; // close enough for mouth animation const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; +const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 100; // See also static AvatarData::defaultFullAvatarModelUrl(). const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default"); From 5a064d3499681c6b1376007e550fb7cea8526010 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 May 2018 14:13:15 +1200 Subject: [PATCH 082/174] Remove selection handles and list highlight when entity deletes --- scripts/system/edit.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index c99c8d401a..9b6b70b954 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -471,6 +471,10 @@ var toolBar = (function () { } } + function checkDeletedEntityAndUpdate(entityID) { + selectionManager.removeEntity(entityID); + } + function initialize() { Script.scriptEnding.connect(cleanup); Window.domainChanged.connect(function () { @@ -493,8 +497,10 @@ var toolBar = (function () { Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate); Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate); Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate); - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); + + Entities.deletingEntity.connect(checkDeletedEntityAndUpdate); + var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); activeButton = tablet.addButton({ From f27e363b6879d6a3e064ee45e91fafcb770ad465 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 May 2018 15:23:13 +1200 Subject: [PATCH 083/174] Remove entity from list when it deletes; handle multiple deletions --- scripts/system/edit.js | 17 ++++++++++++++++- scripts/system/libraries/entitySelectionTool.js | 11 +++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 9b6b70b954..6bb815a597 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -471,8 +471,23 @@ var toolBar = (function () { } } + var entitiesToDelete = []; + var deletedEntityTimer = null; + var DELETE_ENTITY_TIMER_TIMEOUT = 100; + function checkDeletedEntityAndUpdate(entityID) { - selectionManager.removeEntity(entityID); + // Allow for multiple entity deletes before updating the entity list. + entitiesToDelete.push(entityID); + if (deletedEntityTimer !== null) { + Script.clearTimeout(deletedEntityTimer); + } + deletedEntityTimer = Script.setTimeout(function () { + selectionManager.removeEntities(entitiesToDelete); + entityListTool.clearEntityList(); + entityListTool.sendUpdate(); + entitiesToDelete = []; + deletedEntityTimer = null; + }, DELETE_ENTITY_TIMER_TIMEOUT); } function initialize() { diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 2322210522..4996579799 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -149,6 +149,17 @@ SelectionManager = (function() { that._update(true); }; + that.removeEntities = function (entityIDs) { + for (var i = 0, length = entityIDs.length; i < length; i++) { + var idx = that.selections.indexOf(entityIDs[i]); + if (idx >= 0) { + that.selections.splice(idx, 1); + Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityIDs[i]); + } + } + that._update(true); + }; + that.clearSelections = function() { that.selections = []; that._update(true); From 48632be3c2760725d6376f03e227045a1d7220b4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 May 2018 16:12:48 +1200 Subject: [PATCH 084/174] Fix up cache APIs' JSDoc --- libraries/animation/src/AnimationCache.h | 30 +++---- libraries/audio/src/SoundCache.h | 20 ++--- .../src/model-networking/ModelCache.h | 18 ++--- .../src/model-networking/TextureCache.h | 81 +++++++++---------- libraries/networking/src/ResourceCache.h | 18 ++--- 5 files changed, 70 insertions(+), 97 deletions(-) diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 03b37aef2f..103b620254 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -43,45 +43,39 @@ public: * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. */ - // Functions are copied over from ResourceCache (see ResourceCache.h for reason). + // Functions are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc + /**jsdoc * Get the list of all resource URLs. * @function AnimationCache.getResourceList - * @return {string[]} + * @returns {string[]} */ - /**jsdoc + /**jsdoc * @function AnimationCache.dirty * @returns {Signal} */ - /**jsdoc + /**jsdoc * @function AnimationCache.updateTotalSize * @param {number} deltaSize */ - /**jsdoc + /**jsdoc + * Prefetches a resource. * @function AnimationCache.prefetch - * @param {string} url - * @param {object} extra - * @returns {object} + * @param {string} url - URL of the resource to prefetch. + * @param {object} [extra=null] + * @returns {Resource} */ - /**jsdoc + /**jsdoc * Asynchronously loads a resource from the specified URL and returns it. * @function AnimationCache.getResource * @param {string} url - URL of the resource to load. * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. * @param {} [extra=null] - * @return {Resource} - */ - - /**jsdoc - * Prefetches a resource. - * @function AnimationCache.prefetch - * @param {string} url - URL of the resource to prefetch. - * @return {Resource} + * @returns {Resource} */ diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h index d8c52635e0..039e815ff3 100644 --- a/libraries/audio/src/SoundCache.h +++ b/libraries/audio/src/SoundCache.h @@ -36,12 +36,12 @@ public: */ - // Functions are copied over from ResourceCache (see ResourceCache.h for reason). + // Functions are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc * Get the list of all resource URLs. * @function SoundCache.getResourceList - * @return {string[]} + * @returns {string[]} */ /**jsdoc @@ -55,10 +55,11 @@ public: */ /**jsdoc + * Prefetches a resource. * @function SoundCache.prefetch - * @param {string} url - * @param {object} extra - * @returns {object} + * @param {string} url - URL of the resource to prefetch. + * @param {object} [extra=null] + * @returns {Resource} */ /**jsdoc @@ -67,14 +68,7 @@ public: * @param {string} url - URL of the resource to load. * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. * @param {} [extra=null] - * @return {Resource} - */ - - /**jsdoc - * Prefetches a resource. - * @function SoundCache.prefetch - * @param {string} url - URL of the resource to prefetch. - * @return {Resource} + * @returns {Resource} */ diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 9532f39ce0..438c5e0d65 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -156,7 +156,7 @@ public: /**jsdoc * Get the list of all resource URLs. * @function ModelCache.getResourceList - * @return {string[]} + * @returns {string[]} */ /**jsdoc @@ -170,10 +170,11 @@ public: */ /**jsdoc + * Prefetches a resource. * @function ModelCache.prefetch - * @param {string} url - * @param {object} extra - * @returns {object} + * @param {string} url - URL of the resource to prefetch. + * @param {object} [extra=null] + * @returns {Resource} */ /**jsdoc @@ -182,14 +183,7 @@ public: * @param {string} url - URL of the resource to load. * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. * @param {} [extra=null] - * @return {Resource} - */ - - /**jsdoc - * Prefetches a resource. - * @function ModelCache.prefetch - * @param {string} url - URL of the resource to prefetch. - * @return {Resource} + * @returns {Resource} */ diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 3f46dc3074..0c0dbeefa4 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -148,56 +148,50 @@ public: // Properties are copied over from ResourceCache (see ResourceCache.h for reason). /**jsdoc - * API to manage texture cache resources. - * @namespace TextureCache - * - * @property {number} numTotal - Total number of total resources. Read-only. - * @property {number} numCached - Total number of cached resource. Read-only. - * @property {number} sizeTotal - Size in bytes of all resources. Read-only. - * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. - */ + * API to manage texture cache resources. + * @namespace TextureCache + * + * @property {number} numTotal - Total number of total resources. Read-only. + * @property {number} numCached - Total number of cached resource. Read-only. + * @property {number} sizeTotal - Size in bytes of all resources. Read-only. + * @property {number} sizeCached - Size in bytes of all cached resources. Read-only. + */ // Functions are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc - * Get the list of all resource URLs. - * @function TextureCache.getResourceList - * @return {string[]} - */ + /**jsdoc + * Get the list of all resource URLs. + * @function TextureCache.getResourceList + * @returns {string[]} + */ - /**jsdoc - * @function TextureCache.dirty - * @returns {Signal} - */ + /**jsdoc + * @function TextureCache.dirty + * @returns {Signal} + */ - /**jsdoc - * @function TextureCache.updateTotalSize - * @param {number} deltaSize - */ + /**jsdoc + * @function TextureCache.updateTotalSize + * @param {number} deltaSize + */ - /**jsdoc - * @function TextureCache.prefetch - * @param {string} url - * @param {object} extra - * @returns {object} - */ + /**jsdoc + * Prefetches a resource. + * @function TextureCache.prefetch + * @param {string} url - URL of the resource to prefetch. + * @param {object} [extra=null] + * @returns {Resource} + */ - /**jsdoc - * Asynchronously loads a resource from the specified URL and returns it. - * @function TextureCache.getResource - * @param {string} url - URL of the resource to load. - * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. - * @param {} [extra=null] - * @return {Resource} - */ - - /**jsdoc - * Prefetches a resource. - * @function TextureCache.prefetch - * @param {string} url - URL of the resource to prefetch. - * @return {Resource} - */ + /**jsdoc + * Asynchronously loads a resource from the specified URL and returns it. + * @function TextureCache.getResource + * @param {string} url - URL of the resource to load. + * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. + * @param {} [extra=null] + * @returns {Resource} + */ /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture @@ -246,10 +240,11 @@ signals: protected: /**jsdoc - * @function TextureCache.prefect + * @function TextureCache.prefetch * @param {string} url * @param {number} type * @param {number} [maxNumPixels=67108864] + * @returns {Resource} */ // Overload ResourceCache::prefetch to allow specifying texture type for loads Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 609483bc56..8a77beefd4 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -209,7 +209,7 @@ public: /**jsdoc * Get the list of all resource URLs. * @function ResourceCache.getResourceList - * @return {string[]} + * @returns {string[]} */ Q_INVOKABLE QVariantList getResourceList(); @@ -251,10 +251,11 @@ protected slots: void updateTotalSize(const qint64& deltaSize); /**jsdoc + * Prefetches a resource. * @function ResourceCache.prefetch - * @param {string} url - * @param {object} extra - * @returns {object} + * @param {string} url - URL of the resource to prefetch. + * @param {object} [extra=null] + * @returns {Resource} */ // Prefetches a resource to be held by the QScriptEngine. // Left as a protected member so subclasses can overload prefetch @@ -267,7 +268,7 @@ protected slots: * @param {string} url - URL of the resource to load. * @param {string} [fallback=""] - Fallback URL if load of the desired URL fails. * @param {} [extra=null] - * @return {Resource} + * @returns {Resource} */ /// Loads a resource from the specified URL and returns it. /// If the caller is on a different thread than the ResourceCache, @@ -285,12 +286,7 @@ protected: // Pointers created through this method should be owned by the caller, // which should be a QScriptEngine with ScriptableResource registered, so that // the QScriptEngine will delete the pointer when it is garbage collected. - /**jsdoc - * Prefetches a resource. - * @function ResourceCache.prefetch - * @param {string} url - URL of the resource to prefetch. - * @return {Resource} - */ + // JSDoc is provided on more general function signature. Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); } /// Creates a new resource. From 3febdcb141d540075c09739efae715d7543a1e14 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 May 2018 16:15:35 +1200 Subject: [PATCH 085/174] Miscellaneous JSDoc tidying --- interface/src/scripting/SelectionScriptingInterface.h | 6 +++--- .../src/graphics-scripting/GraphicsScriptingInterface.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 71ff41248a..86ececcbca 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -131,7 +131,7 @@ public: /**jsdoc * Get the names of all the selection lists. * @function Selection.getListNames - * @return {list[]} An array of names of all the selection lists. + * @returns {list[]} An array of names of all the selection lists. */ Q_INVOKABLE QStringList getListNames() const; @@ -181,7 +181,7 @@ public: * Get the list of avatars, entities, and overlays stored in a selection list. * @function Selection.getList * @param {string} listName - The name of the selection list. - * @return {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function + * @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function * returns an empty object with no properties. */ Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const; @@ -189,7 +189,7 @@ public: /**jsdoc * Get the names of the highlighted selection lists. * @function Selection.getHighlightedListNames - * @return {string[]} An array of names of the selection list currently highlight enabled. + * @returns {string[]} An array of names of the selection list currently highlight enabled. */ Q_INVOKABLE QStringList getHighlightedListNames() const; diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 526352804b..e0bb39c855 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -39,7 +39,7 @@ public slots: * * @function Graphics.getModel * @param {UUID} entityID - The objectID of the model whose meshes are to be retrieved. - * @return {Graphics.Model} the resulting Model object + * @returns {Graphics.Model} the resulting Model object */ scriptable::ScriptableModelPointer getModel(QUuid uuid); @@ -54,7 +54,7 @@ public slots: * * @function Graphics.newMesh * @param {Graphics.IFSData} ifsMeshData Index-Faced Set (IFS) arrays used to create the new mesh. - * @return {Graphics.Mesh} the resulting Mesh / Mesh Part object + * @returns {Graphics.Mesh} the resulting Mesh / Mesh Part object */ /**jsdoc * @typedef {object} Graphics.IFSData From 05c534991eb182b9e2786548cd32dda8f73f771b Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 2 May 2018 09:39:42 -0700 Subject: [PATCH 086/174] Fix ASAN warnings --- libraries/audio/src/AudioDynamics.h | 31 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index a43833610a..03506fa8a1 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -10,9 +10,9 @@ // Inline functions to implement audio dynamics processing // -#include #include #include +#include #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) @@ -147,13 +147,13 @@ static const int IEEE754_EXPN_BIAS = 127; static inline int32_t peaklog2(float* input) { // float as integer bits - int32_t u = *(int32_t*)input; + uint32_t u = *(uint32_t*)input; // absolute value - int32_t peak = u & IEEE754_FABS_MASK; + uint32_t peak = u & IEEE754_FABS_MASK; // split into e and x - 1.0 - int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; // saturate @@ -183,16 +183,16 @@ static inline int32_t peaklog2(float* input) { static inline int32_t peaklog2(float* input0, float* input1) { // float as integer bits - int32_t u0 = *(int32_t*)input0; - int32_t u1 = *(int32_t*)input1; + uint32_t u0 = *(uint32_t*)input0; + uint32_t u1 = *(uint32_t*)input1; // max absolute value u0 &= IEEE754_FABS_MASK; u1 &= IEEE754_FABS_MASK; - int32_t peak = MAX(u0, u1); + uint32_t peak = MAX(u0, u1); // split into e and x - 1.0 - int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; // saturate @@ -222,20 +222,20 @@ static inline int32_t peaklog2(float* input0, float* input1) { static inline int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) { // float as integer bits - int32_t u0 = *(int32_t*)input0; - int32_t u1 = *(int32_t*)input1; - int32_t u2 = *(int32_t*)input2; - int32_t u3 = *(int32_t*)input3; + uint32_t u0 = *(uint32_t*)input0; + uint32_t u1 = *(uint32_t*)input1; + uint32_t u2 = *(uint32_t*)input2; + uint32_t u3 = *(uint32_t*)input3; // max absolute value u0 &= IEEE754_FABS_MASK; u1 &= IEEE754_FABS_MASK; u2 &= IEEE754_FABS_MASK; u3 &= IEEE754_FABS_MASK; - int32_t peak = MAX(MAX(u0, u1), MAX(u2, u3)); + uint32_t peak = MAX(MAX(u0, u1), MAX(u2, u3)); // split into e and x - 1.0 - int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; // saturate @@ -303,8 +303,7 @@ static inline int32_t fixlog2(int32_t x) { // split into e and x - 1.0 uint32_t u = (uint32_t)x; int e = CLZ(u); - u <<= e; // normalize to [0x80000000, 0xffffffff] - x = u & 0x7fffffff; // x - 1.0 + x = (u << e) & 0x7fffffff; int k = x >> (31 - LOG2_TABBITS); From b29984ab2c8f7efec889c001db5efe58bfeed161 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 1 May 2018 16:52:47 -0700 Subject: [PATCH 087/174] Remove max log age for rolling interface log --- libraries/shared/src/shared/FileLogger.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index 1e17ee9e7c..6a10629ee5 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -36,7 +36,6 @@ protected: private: const FileLogger& _logger; QMutex _fileMutex; - std::chrono::system_clock::time_point _lastRollTime; }; static const QString FILENAME_FORMAT = "hifi-log_%1%2.txt"; @@ -52,7 +51,6 @@ static QUuid SESSION_ID; static const qint64 MAX_LOG_SIZE = 512 * 1024; // Max log files found in the log directory is 100. static const qint64 MAX_LOG_DIR_SIZE = 512 * 1024 * 100; -static const std::chrono::minutes MAX_LOG_AGE { 60 }; static FilePersistThread* _persistThreadInstance; @@ -83,12 +81,10 @@ FilePersistThread::FilePersistThread(const FileLogger& logger) : _logger(logger) if (file.exists()) { rollFileIfNecessary(file, false); } - _lastRollTime = std::chrono::system_clock::now(); } void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfRolled) { - auto now = std::chrono::system_clock::now(); - if ((file.size() > MAX_LOG_SIZE) || (now - _lastRollTime) > MAX_LOG_AGE) { + if (file.size() > MAX_LOG_SIZE) { QString newFileName = getLogRollerFilename(); if (file.copy(newFileName)) { file.open(QIODevice::WriteOnly | QIODevice::Truncate); @@ -97,8 +93,6 @@ void FilePersistThread::rollFileIfNecessary(QFile& file, bool notifyListenersIfR if (notifyListenersIfRolled) { emit rollingLogFile(newFileName); } - - _lastRollTime = std::chrono::system_clock::now(); } QDir logDir(FileUtils::standardPath(LOGS_DIRECTORY)); From 7bad849e67e4ff2ccefb90f3d1c149b06eedacfb Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 15:29:22 -0700 Subject: [PATCH 088/174] Make resource swapchains immutable, fix for 14638 --- .../src/gpu/gl/GLBackendOutput.cpp | 4 ++-- .../src/gpu/gl/GLBackendPipeline.cpp | 7 +++---- libraries/gpu/src/gpu/ResourceSwapChain.h | 19 +++++++---------- .../render-utils/src/AntialiasingEffect.cpp | 21 +++++++++---------- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 2285b0e486..d1ab34da90 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -46,10 +46,10 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { } void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) { - auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset]._uint)); if (swapChain) { auto index = batch._params[paramOffset + 1]._uint; - FramebufferPointer framebuffer = static_cast(swapChain.get())->get(index); + const auto& framebuffer = swapChain->get(index); setFramebuffer(framebuffer); } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp index 58fcc51605..91f1d8bb8c 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp @@ -268,7 +268,7 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si return; } - SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset + 0]._uint)); if (!swapChain) { releaseResourceTexture(slot); @@ -276,9 +276,8 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si } auto index = batch._params[paramOffset + 2]._uint; auto renderBufferSlot = batch._params[paramOffset + 3]._uint; - FramebufferPointer resourceFramebuffer = static_cast(swapChain.get())->get(index); - TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); - + auto resourceFramebuffer = swapChain->get(index); + auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); setResourceTexture(slot, resourceTexture); } diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 7b46b35521..84e8ec7c74 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(unsigned int size = 2U) : _size{ size } {} + SwapChain(size_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - unsigned int getSize() const { return _size; } + size_t getSize() const { return _size; } protected: - unsigned int _size; - unsigned int _frontIndex{ 0U }; + const size_t _size; + size_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -41,16 +41,13 @@ namespace gpu { using Type = R; using TypePointer = std::shared_ptr; + using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(unsigned int size = 2U) : SwapChain{ size } {} - - void reset() { - for (auto& ptr : _resources) { - ptr.reset(); + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + for (size_t i = 0; i < _size; ++i) { + _resources[i] = v[i]; } } - - TypePointer& edit(unsigned int index) { return _resources[(index + _frontIndex) % _size]; } const TypePointer& get(unsigned int index) const { return _resources[(index + _frontIndex) % _size]; } private: diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index e620fc2d61..f77b4fc68b 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -189,7 +189,6 @@ const int AntialiasingPass_NextMapSlot = 4; Antialiasing::Antialiasing(bool isSharpenEnabled) : _isSharpenEnabled{ isSharpenEnabled } { - _antialiasingBuffers = std::make_shared(2U); } Antialiasing::~Antialiasing() { @@ -321,25 +320,25 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const int width = sourceBuffer->getWidth(); int height = sourceBuffer->getHeight(); - if (_antialiasingBuffers->get(0)) { - if (_antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {// || (sourceBuffer && (_antialiasingBuffer->getRenderBuffer(1) != sourceBuffer->getRenderBuffer(0)))) { - _antialiasingBuffers->edit(0).reset(); - _antialiasingBuffers->edit(1).reset(); - _antialiasingTextures[0].reset(); - _antialiasingTextures[1].reset(); - } + if (_antialiasingBuffers && _antialiasingBuffers->get(0) && _antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) { + _antialiasingBuffers.reset(); + _antialiasingTextures[0].reset(); + _antialiasingTextures[1].reset(); } - if (!_antialiasingBuffers->get(0)) { + + if (!_antialiasingBuffers) { + std::vector antiAliasingBuffers; // Link the antialiasing FBO to texture auto format = sourceBuffer->getRenderBuffer(0)->getTexelFormat(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); for (int i = 0; i < 2; i++) { - auto& antiAliasingBuffer = _antialiasingBuffers->edit(i); - antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing")); + antiAliasingBuffers.emplace_back(gpu::Framebuffer::create("antialiasing")); + const auto& antiAliasingBuffer = antiAliasingBuffers.back(); _antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]); } + _antialiasingBuffers = std::make_shared(antiAliasingBuffers); } gpu::doInBatch("Antialiasing::run", args->_context, [&](gpu::Batch& batch) { From 233c60a5063573cb55770b382013deeefadfba6f Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 16:54:26 -0700 Subject: [PATCH 089/174] Change type used for swap chain count --- libraries/gpu/src/gpu/ResourceSwapChain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 84e8ec7c74..28c5ff2ed3 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(size_t size = 2U) : _size{ size } {} + SwapChain(uint8_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - size_t getSize() const { return _size; } + uint8_t getSize() const { return _size; } protected: - const size_t _size; - size_t _frontIndex{ 0U }; + const uint8_t _size; + uint8_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -43,7 +43,7 @@ namespace gpu { using TypePointer = std::shared_ptr; using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min((uint8_t)v.size(), MAX_SIZE) } { for (size_t i = 0; i < _size; ++i) { _resources[i] = v[i]; } From 80f87f7a6264d6e06f1340771fe0345f5e180ea5 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 15:29:22 -0700 Subject: [PATCH 090/174] Make resource swapchains immutable, fix for 14638 --- .../src/gpu/gl/GLBackendOutput.cpp | 4 ++-- .../src/gpu/gl/GLBackendPipeline.cpp | 7 +++---- libraries/gpu/src/gpu/ResourceSwapChain.h | 19 +++++++---------- .../render-utils/src/AntialiasingEffect.cpp | 21 +++++++++---------- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 2285b0e486..d1ab34da90 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -46,10 +46,10 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { } void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) { - auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset]._uint)); if (swapChain) { auto index = batch._params[paramOffset + 1]._uint; - FramebufferPointer framebuffer = static_cast(swapChain.get())->get(index); + const auto& framebuffer = swapChain->get(index); setFramebuffer(framebuffer); } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp index 58fcc51605..91f1d8bb8c 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp @@ -268,7 +268,7 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si return; } - SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset + 0]._uint)); if (!swapChain) { releaseResourceTexture(slot); @@ -276,9 +276,8 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si } auto index = batch._params[paramOffset + 2]._uint; auto renderBufferSlot = batch._params[paramOffset + 3]._uint; - FramebufferPointer resourceFramebuffer = static_cast(swapChain.get())->get(index); - TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); - + auto resourceFramebuffer = swapChain->get(index); + auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); setResourceTexture(slot, resourceTexture); } diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 7b46b35521..84e8ec7c74 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(unsigned int size = 2U) : _size{ size } {} + SwapChain(size_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - unsigned int getSize() const { return _size; } + size_t getSize() const { return _size; } protected: - unsigned int _size; - unsigned int _frontIndex{ 0U }; + const size_t _size; + size_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -41,16 +41,13 @@ namespace gpu { using Type = R; using TypePointer = std::shared_ptr; + using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(unsigned int size = 2U) : SwapChain{ size } {} - - void reset() { - for (auto& ptr : _resources) { - ptr.reset(); + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + for (size_t i = 0; i < _size; ++i) { + _resources[i] = v[i]; } } - - TypePointer& edit(unsigned int index) { return _resources[(index + _frontIndex) % _size]; } const TypePointer& get(unsigned int index) const { return _resources[(index + _frontIndex) % _size]; } private: diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index dd4bda2e37..c9aa1b8f71 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -189,7 +189,6 @@ const int AntialiasingPass_NextMapSlot = 4; Antialiasing::Antialiasing(bool isSharpenEnabled) : _isSharpenEnabled{ isSharpenEnabled } { - _antialiasingBuffers = std::make_shared(2U); } Antialiasing::~Antialiasing() { @@ -325,25 +324,25 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const int width = sourceBuffer->getWidth(); int height = sourceBuffer->getHeight(); - if (_antialiasingBuffers->get(0)) { - if (_antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {// || (sourceBuffer && (_antialiasingBuffer->getRenderBuffer(1) != sourceBuffer->getRenderBuffer(0)))) { - _antialiasingBuffers->edit(0).reset(); - _antialiasingBuffers->edit(1).reset(); - _antialiasingTextures[0].reset(); - _antialiasingTextures[1].reset(); - } + if (_antialiasingBuffers && _antialiasingBuffers->get(0) && _antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) { + _antialiasingBuffers.reset(); + _antialiasingTextures[0].reset(); + _antialiasingTextures[1].reset(); } - if (!_antialiasingBuffers->get(0)) { + + if (!_antialiasingBuffers) { + std::vector antiAliasingBuffers; // Link the antialiasing FBO to texture auto format = sourceBuffer->getRenderBuffer(0)->getTexelFormat(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); for (int i = 0; i < 2; i++) { - auto& antiAliasingBuffer = _antialiasingBuffers->edit(i); - antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing")); + antiAliasingBuffers.emplace_back(gpu::Framebuffer::create("antialiasing")); + const auto& antiAliasingBuffer = antiAliasingBuffers.back(); _antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]); } + _antialiasingBuffers = std::make_shared(antiAliasingBuffers); } gpu::doInBatch("Antialiasing::run", args->_context, [&](gpu::Batch& batch) { From 64d442b281713262ff43868c3366e514a452bbfa Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 16:54:26 -0700 Subject: [PATCH 091/174] Change type used for swap chain count --- libraries/gpu/src/gpu/ResourceSwapChain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 84e8ec7c74..28c5ff2ed3 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(size_t size = 2U) : _size{ size } {} + SwapChain(uint8_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - size_t getSize() const { return _size; } + uint8_t getSize() const { return _size; } protected: - const size_t _size; - size_t _frontIndex{ 0U }; + const uint8_t _size; + uint8_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -43,7 +43,7 @@ namespace gpu { using TypePointer = std::shared_ptr; using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min((uint8_t)v.size(), MAX_SIZE) } { for (size_t i = 0; i < _size; ++i) { _resources[i] = v[i]; } From 4fa9af5534b483b7b53a794e9d0c36ea723c3a4f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 20 Apr 2018 11:38:25 -0700 Subject: [PATCH 092/174] Added items to the developer menu for debugging physics Hooked up Bullet's internal debug draw functionality to our client. Under the Developer > Physics Menu there are five new items: * Show Bullet Collision - will draw all collision shapes in wireframe. WARNING: can be slow on large scenes. * Show Bullet Bounding Boxes - will draw axis aligned bounding boxes around all physics shapes. * Show Bullet Contact Points - will draw all contact points where two or more objects are colliding. * Show Bullet Constraints - will render wire frame axes for each constraint connecting bodies together. * Show Bullet Constraint Limits - will render the joint limits for each constraint. --- interface/src/Application.cpp | 20 +++++++ interface/src/Application.h | 7 +++ interface/src/Menu.cpp | 6 +++ interface/src/Menu.h | 5 ++ libraries/physics/src/PhysicsDebugDraw.cpp | 54 +++++++++++++++++++ libraries/physics/src/PhysicsDebugDraw.h | 34 ++++++++++++ libraries/physics/src/PhysicsEngine.cpp | 55 ++++++++++++++++++++ libraries/physics/src/PhysicsEngine.h | 8 +++ libraries/render-utils/src/AnimDebugDraw.cpp | 12 ++--- 9 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 libraries/physics/src/PhysicsDebugDraw.cpp create mode 100644 libraries/physics/src/PhysicsDebugDraw.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd4562da54..880f7a2213 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7828,6 +7828,26 @@ void Application::switchDisplayMode() { _previousHMDWornStatus = currentHMDWornStatus; } +void Application::setShowBulletWireframe(bool value) { + _physicsEngine->setShowBulletWireframe(value); +} + +void Application::setShowBulletAABBs(bool value) { + _physicsEngine->setShowBulletAABBs(value); +} + +void Application::setShowBulletContactPoints(bool value) { + _physicsEngine->setShowBulletContactPoints(value); +} + +void Application::setShowBulletConstraints(bool value) { + _physicsEngine->setShowBulletConstraints(value); +} + +void Application::setShowBulletConstraintLimits(bool value) { + _physicsEngine->setShowBulletConstraintLimits(value); +} + void Application::startHMDStandBySession() { _autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 6d611bc8e2..ce7abf7099 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -243,6 +243,7 @@ public: bool isAboutToQuit() const { return _aboutToQuit; } bool isPhysicsEnabled() const { return _physicsEnabled; } + PhysicsEnginePointer getPhysicsEngine() { return _physicsEngine; } // the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display // rendering of several elements depend on that @@ -453,6 +454,12 @@ private slots: void handleSandboxStatus(QNetworkReply* reply); void switchDisplayMode(); + void setShowBulletWireframe(bool value); + void setShowBulletAABBs(bool value); + void setShowBulletContactPoints(bool value); + void setShowBulletConstraints(bool value); + void setShowBulletConstraintLimits(bool value); + private: void init(); bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 50ff65ad1a..60d5abf260 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -735,6 +735,12 @@ Menu::Menu() { } addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls, 0, false, qApp->getEntities().data(), SIGNAL(setRenderDebugHulls())); + addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletWireframe, 0, false, qApp, SLOT(setShowBulletWireframe(bool))); + addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletAABBs, 0, false, qApp, SLOT(setShowBulletAABBs(bool))); + addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletContactPoints, 0, false, qApp, SLOT(setShowBulletContactPoints(bool))); + addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletConstraints, 0, false, qApp, SLOT(setShowBulletConstraints(bool))); + addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletConstraintLimits, 0, false, qApp, SLOT(setShowBulletConstraintLimits(bool))); + // Developer > Ask to Reset Settings addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AskToResetSettings, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c8c8ee42df..20375a71b2 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -143,6 +143,11 @@ namespace MenuOption { const QString PhysicsShowHulls = "Draw Collision Shapes"; const QString PhysicsShowOwned = "Highlight Simulation Ownership"; const QString VerboseLogging = "Verbose Logging"; + const QString PhysicsShowBulletWireframe = "Show Bullet Collision"; + const QString PhysicsShowBulletAABBs = "Show Bullet Bounding Boxes"; + const QString PhysicsShowBulletContactPoints = "Show Bullet Contact Points"; + const QString PhysicsShowBulletConstraints = "Show Bullet Constraints"; + const QString PhysicsShowBulletConstraintLimits = "Show Bullet Constraint Limits"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "General..."; const QString Quit = "Quit"; diff --git a/libraries/physics/src/PhysicsDebugDraw.cpp b/libraries/physics/src/PhysicsDebugDraw.cpp new file mode 100644 index 0000000000..b2911219d5 --- /dev/null +++ b/libraries/physics/src/PhysicsDebugDraw.cpp @@ -0,0 +1,54 @@ +// +// PhysicsDebugDraw.cpp +// libraries/physics/src +// +// Created by Anthony Thibault 2018-4-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 "PhysicsDebugDraw.h" +#include "BulletUtil.h" +#include "PhysicsLogging.h" + +#include +#include + +void PhysicsDebugDraw::drawLine(const btVector3& from, const btVector3& to, const btVector3& color) { + DebugDraw::getInstance().drawRay(bulletToGLM(from), bulletToGLM(to), glm::vec4(color.getX(), color.getY(), color.getZ(), 1.0f)); +} + +void PhysicsDebugDraw::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, + int lifeTime, const btVector3& color) { + + glm::vec3 normal, tangent, biNormal; + generateBasisVectors(bulletToGLM(normalOnB), Vectors::UNIT_X, normal, tangent, biNormal); + btVector3 u = glmToBullet(normal); + btVector3 v = glmToBullet(tangent); + btVector3 w = glmToBullet(biNormal); + + // x marks the spot, green is along the normal. + const float CONTACT_POINT_RADIUS = 0.1f; + const btVector3 GREEN(0.0f, 1.0f, 0.0f); + const btVector3 WHITE(1.0f, 1.0f, 1.0f); + drawLine(PointOnB - u * CONTACT_POINT_RADIUS, PointOnB + u * CONTACT_POINT_RADIUS, GREEN); + drawLine(PointOnB - v * CONTACT_POINT_RADIUS, PointOnB + v * CONTACT_POINT_RADIUS, WHITE); + drawLine(PointOnB - w * CONTACT_POINT_RADIUS, PointOnB + w * CONTACT_POINT_RADIUS, WHITE); +} + +void PhysicsDebugDraw::reportErrorWarning(const char* warningString) { + qCWarning(physics) << "BULLET:" << warningString; +} + +void PhysicsDebugDraw::draw3dText(const btVector3& location, const char* textString) { +} + +void PhysicsDebugDraw::setDebugMode(int debugMode) { + _debugDrawMode = debugMode; +} + +int PhysicsDebugDraw::getDebugMode() const { + return _debugDrawMode; +} diff --git a/libraries/physics/src/PhysicsDebugDraw.h b/libraries/physics/src/PhysicsDebugDraw.h new file mode 100644 index 0000000000..f653136474 --- /dev/null +++ b/libraries/physics/src/PhysicsDebugDraw.h @@ -0,0 +1,34 @@ +// +// PhysicsDebugDraw.h +// libraries/physics/src +// +// Created by Anthony Thibault 2018-4-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 +// +// http://bulletphysics.org/Bullet/BulletFull/classbtIDebugDraw.html + +#ifndef hifi_PhysicsDebugDraw_h +#define hifi_PhysicsDebugDraw_h + +#include +#include + +class PhysicsDebugDraw : public btIDebugDraw { +public: + using btIDebugDraw::drawLine; + virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override; + virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, + int lifeTime, const btVector3& color) override; + virtual void reportErrorWarning(const char* warningString) override; + virtual void draw3dText(const btVector3& location, const char* textString) override; + virtual void setDebugMode(int debugMode) override; + virtual int getDebugMode() const override; + +protected: + uint32_t _debugDrawMode; +}; + +#endif // hifi_PhysicsDebugDraw_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 7c2ad55405..50d516c256 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -22,6 +22,7 @@ #include "ObjectMotionState.h" #include "PhysicsEngine.h" #include "PhysicsHelpers.h" +#include "PhysicsDebugDraw.h" #include "ThreadSafeDynamicsWorld.h" #include "PhysicsLogging.h" @@ -49,6 +50,10 @@ void PhysicsEngine::init() { _broadphaseFilter = new btDbvtBroadphase(); _constraintSolver = new btSequentialImpulseConstraintSolver; _dynamicsWorld = new ThreadSafeDynamicsWorld(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig); + _physicsDebugDraw.reset(new PhysicsDebugDraw()); + + // hook up debug draw renderer + _dynamicsWorld->setDebugDrawer(_physicsDebugDraw.get()); _ghostPairCallback = new btGhostPairCallback(); _dynamicsWorld->getPairCache()->setInternalGhostPairCallback(_ghostPairCallback); @@ -333,6 +338,10 @@ void PhysicsEngine::stepSimulation() { _hasOutgoingChanges = true; } + + if (_physicsDebugDraw->getDebugMode()) { + _dynamicsWorld->debugDrawWorld(); + } } class CProfileOperator { @@ -785,3 +794,49 @@ void PhysicsEngine::forEachDynamic(std::function act } } } + +void PhysicsEngine::setShowBulletWireframe(bool value) { + int mode = _physicsDebugDraw->getDebugMode(); + if (value) { + _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawWireframe); + } else { + _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawWireframe); + } +} + +void PhysicsEngine::setShowBulletAABBs(bool value) { + int mode = _physicsDebugDraw->getDebugMode(); + if (value) { + _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawAabb); + } else { + _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawAabb); + } +} + +void PhysicsEngine::setShowBulletContactPoints(bool value) { + int mode = _physicsDebugDraw->getDebugMode(); + if (value) { + _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawContactPoints); + } else { + _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawContactPoints); + } +} + +void PhysicsEngine::setShowBulletConstraints(bool value) { + int mode = _physicsDebugDraw->getDebugMode(); + if (value) { + _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawConstraints); + } else { + _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawConstraints); + } +} + +void PhysicsEngine::setShowBulletConstraintLimits(bool value) { + int mode = _physicsDebugDraw->getDebugMode(); + if (value) { + _physicsDebugDraw->setDebugMode(mode | btIDebugDraw::DBG_DrawConstraintLimits); + } else { + _physicsDebugDraw->setDebugMode(mode & ~btIDebugDraw::DBG_DrawConstraintLimits); + } +} + diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 92d2e6885a..0dfe3a7a7c 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -30,6 +30,7 @@ const float HALF_SIMULATION_EXTENT = 512.0f; // meters class CharacterController; +class PhysicsDebugDraw; // simple class for keeping track of contacts class ContactKey { @@ -96,6 +97,12 @@ public: void removeDynamic(const QUuid dynamicID); void forEachDynamic(std::function actor); + void setShowBulletWireframe(bool value); + void setShowBulletAABBs(bool value); + void setShowBulletContactPoints(bool value); + void setShowBulletConstraints(bool value); + void setShowBulletConstraintLimits(bool value); + private: QList removeDynamicsForBody(btRigidBody* body); void addObjectToDynamicsWorld(ObjectMotionState* motionState); @@ -114,6 +121,7 @@ private: btSequentialImpulseConstraintSolver* _constraintSolver = NULL; ThreadSafeDynamicsWorld* _dynamicsWorld = NULL; btGhostPairCallback* _ghostPairCallback = NULL; + std::unique_ptr _physicsDebugDraw; ContactMap _contactMap; CollisionEvents _collisionEvents; diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 7086b65f4c..eca500f36c 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -52,9 +52,9 @@ public: batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex)); - batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0); + batch.setIndexBuffer(gpu::UINT32, _indexBuffer, 0); - auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t); + auto numIndices = _indexBuffer->getSize() / sizeof(uint32_t); batch.drawIndexed(gpu::LINES, (int)numIndices); } @@ -135,9 +135,9 @@ AnimDebugDraw::AnimDebugDraw() : AnimDebugDrawData::Vertex { glm::vec3(1.0, 1.0f, 1.0f), toRGBA(0, 0, 255, 255) }, AnimDebugDrawData::Vertex { glm::vec3(1.0, 1.0f, 2.0f), toRGBA(0, 0, 255, 255) }, }); - static std::vector indices({ 0, 1, 2, 3, 4, 5 }); + static std::vector indices({ 0, 1, 2, 3, 4, 5 }); _animDebugDrawData->_vertexBuffer->setSubData(0, vertices); - _animDebugDrawData->_indexBuffer->setSubData(0, indices); + _animDebugDrawData->_indexBuffer->setSubData(0, indices); } AnimDebugDraw::~AnimDebugDraw() { @@ -425,9 +425,9 @@ void AnimDebugDraw::update() { data._isVisible = (numVerts > 0); - data._indexBuffer->resize(sizeof(uint16_t) * numVerts); + data._indexBuffer->resize(sizeof(uint32_t) * numVerts); for (int i = 0; i < numVerts; i++) { - data._indexBuffer->setSubData(i, (uint16_t)i);; + data._indexBuffer->setSubData(i, (uint32_t)i);; } }); scene->enqueueTransaction(transaction); From 689fbd2da07aeb30f698e06b4b7d166367aac8fe Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 2 May 2018 11:09:17 -0700 Subject: [PATCH 093/174] added requested changes --- interface/src/Application.cpp | 30 ++++++++----------- interface/src/ModelPackager.cpp | 1 - interface/src/avatar/MyAvatar.cpp | 5 ++++ interface/src/avatar/MyAvatar.h | 2 ++ libraries/fbx/src/FSTReader.cpp | 16 +++++----- .../src/model-networking/ModelCache.cpp | 6 ++-- 6 files changed, 29 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ec40ffc653..b384e1086e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1231,7 +1231,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] { getEntities()->reloadEntityScripts(); - loadAvatarScripts(getMyAvatar()->getSkeletonModel()->getFBXGeometry().scripts); + loadAvatarScripts(getMyAvatar()->getScriptUrls()); }, Qt::QueuedConnection); connect(scriptEngines, &ScriptEngines::scriptLoadError, @@ -4728,16 +4728,14 @@ void Application::init() { } void Application::loadAvatarScripts(const QVector& urls) { - if (urls.size() > 0) { - auto scriptEngines = DependencyManager::get(); - auto runningScripts = scriptEngines->getRunningScripts(); - for (auto url : urls) { - int index = runningScripts.indexOf(url); - if (index < 0) { - auto scriptEnginePointer = scriptEngines->loadScript(url, false); - if (scriptEnginePointer) { - scriptEnginePointer->setType(ScriptEngine::Type::AVATAR); - } + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto url : urls) { + int index = runningScripts.indexOf(url); + if (index < 0) { + auto scriptEnginePointer = scriptEngines->loadScript(url, false); + if (scriptEnginePointer) { + scriptEnginePointer->setType(ScriptEngine::Type::AVATAR); } } } @@ -4746,12 +4744,10 @@ void Application::loadAvatarScripts(const QVector& urls) { void Application::unloadAvatarScripts() { auto scriptEngines = DependencyManager::get(); auto urls = scriptEngines->getRunningScripts(); - if (urls.size() > 0) { - for (auto url : urls) { - auto scriptEngine = scriptEngines->getScriptEngine(url); - if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) { - scriptEngines->stopScript(url, false); - } + for (auto url : urls) { + auto scriptEngine = scriptEngines->getScriptEngine(url); + if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) { + scriptEngines->stopScript(url, false); } } } diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 72b99ce5a3..0e34eebc80 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -210,7 +210,6 @@ bool ModelPackager::zipModel() { _mapping[TEXDIR_FIELD] = tempDir.relativeFilePath(texDir.path()); for (auto multi : _mapping.values(SCRIPT_FIELD)) { - multi.fromValue(tempDir.relativeFilePath(scriptDir.path()) + multi.toString()); } // Copy FST diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 85b2ece077..5ce056e9b7 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2852,6 +2852,11 @@ void MyAvatar::setWalkSpeed(float value) { _walkSpeed.set(value); } +QVector MyAvatar::getScriptUrls() { + QVector scripts = _skeletonModel->isLoaded() ? _skeletonModel->getFBXGeometry().scripts : QVector(); + return scripts; +} + glm::vec3 MyAvatar::getPositionForAudio() { glm::vec3 result; switch (_audioListenerMode) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2bcbd878a9..d605e1cc44 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,6 +594,8 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; + QVector getScriptUrls(); + public slots: void increaseSize(); void decreaseSize(); diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index fcbfca1e7d..d63a5b3cc4 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -193,17 +193,15 @@ QVector FSTReader::getScripts(const QUrl& url, const QVariantHash& mapp QVector scriptPaths; if (!fstMapping.value(SCRIPT_FIELD).isNull()) { auto scripts = fstMapping.values(SCRIPT_FIELD).toVector(); - if (scripts.size() > 0) { - for (auto &script : scripts) { - QString scriptPath = script.toString(); - if (QUrl(scriptPath).isRelative()) { - if (scriptPath.at(0) == '/') { - scriptPath = scriptPath.right(scriptPath.length() - 1); - } - scriptPath = url.resolved(QUrl(scriptPath)).toString(); + for (auto &script : scripts) { + QString scriptPath = script.toString(); + if (QUrl(scriptPath).isRelative()) { + if (scriptPath.at(0) == '/') { + scriptPath = scriptPath.right(scriptPath.length() - 1); } - scriptPaths.push_back(scriptPath); + scriptPath = url.resolved(QUrl(scriptPath)).toString(); } + scriptPaths.push_back(scriptPath); } } return scriptPaths; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index e1086bc0c9..416920d43f 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -221,10 +221,8 @@ void GeometryReader::run() { // Add scripts to fbxgeometry if (!_mapping.value(SCRIPT_FIELD).isNull()) { QVariantList scripts = _mapping.values(SCRIPT_FIELD); - if (scripts.size() > 0) { - for (auto &script : scripts) { - fbxGeometry->scripts.push_back(script.toString()); - } + for (auto &script : scripts) { + fbxGeometry->scripts.push_back(script.toString()); } } From 697fde4a1a247437ea730cdb642f470e395b0ecd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 2 May 2018 13:31:32 -0700 Subject: [PATCH 094/174] Cleanup meta texture related changes --- libraries/baking/src/FBXBaker.cpp | 56 ------------------- libraries/baking/src/ModelBaker.cpp | 4 -- libraries/baking/src/TextureBaker.cpp | 11 ++-- libraries/fbx/src/FBXReader.cpp | 1 - libraries/fbx/src/FBXReader_Material.cpp | 4 -- .../src/model-networking/TextureCache.cpp | 10 +--- libraries/networking/src/ResourceCache.cpp | 2 - 7 files changed, 6 insertions(+), 82 deletions(-) diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 175698eeea..c8ba98f0b1 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -74,62 +74,6 @@ void FBXBaker::bakeSourceCopy() { checkIfTexturesFinished(); } -void FBXBaker::embedTextureMetaData() { - std::vector embeddedTextureNodes; - - for (FBXNode& rootChild : _rootNode.children) { - if (rootChild.name == "Objects") { - qlonglong maxId = 0; - for (auto &child : rootChild.children) { - if (child.properties.length() == 3) { - maxId = std::max(maxId, child.properties[0].toLongLong()); - } - } - - for (auto& object : rootChild.children) { - if (object.name == "Texture") { - QVariant relativeFilename; - for (auto& child : object.children) { - if (child.name == "RelativeFilename") { - relativeFilename = child.properties[0]; - break; - } - } - - if (relativeFilename.isNull() || !relativeFilename.toString().endsWith(BAKED_META_TEXTURE_SUFFIX)) { - continue; - } - - FBXNode videoNode; - videoNode.name = "Video"; - videoNode.properties.append(++maxId); - videoNode.properties.append(object.properties[1]); - videoNode.properties.append("Clip"); - - QString bakedTextureFilePath { - _bakedOutputDir + "/" + relativeFilename.toString() - }; - qDebug() << "Location of texture: " << bakedTextureFilePath; - - QFile textureFile { bakedTextureFilePath }; - if (!textureFile.open(QIODevice::ReadOnly)) { - qWarning() << "Failed to open: " << bakedTextureFilePath; - continue; - } - - videoNode.children.append({ "RelativeFilename", { relativeFilename }, { } }); - videoNode.children.append({ "Content", { textureFile.readAll() }, { } }); - - rootChild.children.append(videoNode); - - textureFile.close(); - } - } - } - } - -} - void FBXBaker::setupOutputFolder() { // make sure there isn't already an output directory using the same name if (QDir(_bakedOutputDir).exists()) { diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index 020a0dbfc2..ee26b94b81 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -537,8 +537,6 @@ void ModelBaker::embedTextureMetaData() { } } - qDebug() << "Max id found was: " << maxId; - for (auto& object : rootChild.children) { if (object.name == "Texture") { QVariant relativeFilename; @@ -567,7 +565,6 @@ void ModelBaker::embedTextureMetaData() { QString bakedTextureFilePath { _bakedOutputDir + "/" + relativeFilename.toString() }; - qDebug() << "Location of texture: " << bakedTextureFilePath; QFile textureFile { bakedTextureFilePath }; if (!textureFile.open(QIODevice::ReadOnly)) { @@ -585,7 +582,6 @@ void ModelBaker::embedTextureMetaData() { } } } - } void ModelBaker::exportScene() { diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index 7a5dc85a61..45895494a0 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -128,11 +128,11 @@ void TextureBaker::processTexture() { auto filePath = _outputDirectory.absoluteFilePath(_textureURL.fileName()); QFile file { filePath }; if (!file.open(QIODevice::WriteOnly) || file.write(_originalTexture) == -1) { - handleError("Could not write meta texture for " + _textureURL.toString()); + handleError("Could not write original texture for " + _textureURL.toString()); return; } _outputFiles.push_back(filePath); - meta.original =_metaTexturePathPrefix +_textureURL.fileName(); + meta.original = _metaTexturePathPrefix +_textureURL.fileName(); } // IMPORTANT: _originalTexture is empty past this point @@ -157,18 +157,17 @@ void TextureBaker::processTexture() { return; } - const char* data = reinterpret_cast(memKTX->_storage->data()); - const size_t length = memKTX->_storage->size(); const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat()); if (name == nullptr) { handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString()); return; } - qDebug() << "Found type: " << name; - // attempt to write the baked texture to the destination file path { + const char* data = reinterpret_cast(memKTX->_storage->data()); + const size_t length = memKTX->_storage->size(); + auto fileName = _baseFilename + BAKED_TEXTURE_BCN_SUFFIX; auto filePath = _outputDirectory.absoluteFilePath(fileName); QFile bakedTextureFile { filePath }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1f237edfb0..1e59646795 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1101,7 +1101,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } if (!content.isEmpty()) { _textureContent.insert(filepath, content); - qDebug() << "Adding content: " << filepath << content.length(); } } else if (object.name == "Material") { FBXMaterial material; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 88dc7f599d..4aa3044934 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -85,16 +85,12 @@ FBXTexture FBXReader::getTexture(const QString& textureID) { FBXTexture texture; const QByteArray& filepath = _textureFilepaths.value(textureID); texture.content = _textureContent.value(filepath); - qDebug() << "Getting texture: " << textureID << filepath << texture.content.length(); if (texture.content.isEmpty()) { // the content is not inlined - qDebug() << "Texture is not inlined"; texture.filename = _textureFilenames.value(textureID); } else { // use supplied filepath for inlined content - qDebug() << "Texture is inlined"; texture.filename = filepath; } - qDebug() << "Path: " << texture.filename; texture.id = textureID; texture.name = _textureNames.value(textureID); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 54b654c56b..241c4eef3b 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -315,7 +315,6 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, _textureSource = std::make_shared(url, (int)type); _lowestRequestedMipLevel = 0; - qDebug() << "Creating networktexture: " << url; if (url.fileName().endsWith(TEXTURE_META_EXTENSION)) { _currentlyLoadingResourceType = ResourceType::META; } else if (url.fileName().endsWith(".ktx")) { @@ -402,7 +401,6 @@ NetworkTexture::~NetworkTexture() { const uint16_t NetworkTexture::NULL_MIP_LEVEL = std::numeric_limits::max(); void NetworkTexture::makeRequest() { - qDebug() << "In makeRequest for " << _activeUrl << (int)_currentlyLoadingResourceType; if (_currentlyLoadingResourceType != ResourceType::KTX) { Resource::makeRequest(); return; @@ -454,7 +452,6 @@ void NetworkTexture::makeRequest() { _ktxHeaderRequest->send(); - qDebug() << "Starting mip range request"; startMipRangeRequest(NULL_MIP_LEVEL, NULL_MIP_LEVEL); } else if (_ktxResourceState == PENDING_MIP_REQUEST) { if (_lowestKnownPopulatedMip > 0) { @@ -594,7 +591,6 @@ void NetworkTexture::startMipRangeRequest(uint16_t low, uint16_t high) { bool isHighMipRequest = low == NULL_MIP_LEVEL && high == NULL_MIP_LEVEL; - qDebug() << "Making ktx mip request to: " << _activeUrl; _ktxMipRequest = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_ktxMipRequest) { @@ -944,9 +940,7 @@ void NetworkTexture::handleFinishedInitialLoad() { } void NetworkTexture::downloadFinished(const QByteArray& data) { - qDebug() << "Loading content: " << _activeUrl; if (_currentlyLoadingResourceType == ResourceType::META) { - qDebug() << "Loading meta content: " << _activeUrl; loadMetaContent(data); } else if (_currentlyLoadingResourceType == ResourceType::ORIGINAL) { loadTextureContent(data); @@ -984,7 +978,6 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) { _currentlyLoadingResourceType = ResourceType::KTX; _activeUrl = _activeUrl.resolved(url); - qDebug() << "Active url is now: " << _activeUrl; auto textureCache = DependencyManager::get(); auto self = _self.lock(); if (!self) { @@ -1010,13 +1003,12 @@ void NetworkTexture::loadMetaContent(const QByteArray& content) { } qWarning() << "Failed to find supported texture type in " << _activeUrl; - //TextureCache::requestCompleted(_self); Resource::handleFailedRequest(ResourceRequest::NotFound); } void NetworkTexture::loadTextureContent(const QByteArray& content) { if (_currentlyLoadingResourceType != ResourceType::ORIGINAL) { - qWarning() << "Trying to load texture content when currentl resource type is not ORIGINAL"; + qWarning() << "Trying to load texture content when current resource type is not ORIGINAL"; assert(false); return; } diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 4d3ba9da25..4d1bfdea66 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -619,7 +619,6 @@ void Resource::init(bool resetLoaded) { _loaded = false; } _attempts = 0; - qDebug() << "Initting resource: " << _url; if (_url.isEmpty()) { _startedLoading = _loaded = true; @@ -672,7 +671,6 @@ void Resource::makeRequest() { PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } }); - qDebug() << "Making request to " << _activeUrl; _request = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_request) { From 529869e80c79bd281d60e526d0a3fce219132c55 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 2 May 2018 13:41:52 -0700 Subject: [PATCH 095/174] Make NetworkTexture extension comparisons case-insensitive --- .../model-networking/src/model-networking/TextureCache.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 241c4eef3b..ed21fd35bc 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -315,9 +315,10 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, _textureSource = std::make_shared(url, (int)type); _lowestRequestedMipLevel = 0; - if (url.fileName().endsWith(TEXTURE_META_EXTENSION)) { + auto fileNameLowercase = url.fileName().toLower(); + if (fileNameLowercase.endsWith(TEXTURE_META_EXTENSION)) { _currentlyLoadingResourceType = ResourceType::META; - } else if (url.fileName().endsWith(".ktx")) { + } else if (fileNameLowercase.endsWith(".ktx")) { _currentlyLoadingResourceType = ResourceType::KTX; } else { _currentlyLoadingResourceType = ResourceType::ORIGINAL; From 4a96dc2fdc4b4c722d8f342d1c33876273b08fc5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 3 May 2018 08:48:17 +1200 Subject: [PATCH 096/174] Refactor --- scripts/system/libraries/entitySelectionTool.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 4996579799..36cc98a80b 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -140,22 +140,22 @@ SelectionManager = (function() { that._update(true); }; - that.removeEntity = function(entityID) { + function removeEntityByID(entityID) { var idx = that.selections.indexOf(entityID); if (idx >= 0) { that.selections.splice(idx, 1); Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID); } + } + + that.removeEntity = function (entityID) { + removeEntityByID(entityID); that._update(true); }; that.removeEntities = function (entityIDs) { for (var i = 0, length = entityIDs.length; i < length; i++) { - var idx = that.selections.indexOf(entityIDs[i]); - if (idx >= 0) { - that.selections.splice(idx, 1); - Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityIDs[i]); - } + removeEntityByID(entityIDs[i]); } that._update(true); }; From 5312c81a6fe7be0ca5b5c90bbab24d91e2d14963 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 3 May 2018 08:49:18 +1200 Subject: [PATCH 097/174] Match style of surrounding code --- scripts/system/libraries/entitySelectionTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 36cc98a80b..e84600a64a 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -153,7 +153,7 @@ SelectionManager = (function() { that._update(true); }; - that.removeEntities = function (entityIDs) { + that.removeEntities = function(entityIDs) { for (var i = 0, length = entityIDs.length; i < length; i++) { removeEntityByID(entityIDs[i]); } From e0b16dfe03493caf8f8aae8cbe02393b21d66df5 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 14:17:01 -0700 Subject: [PATCH 098/174] Allow use of `--url` command line argument in test mode. --- interface/src/Application.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eb59576cc0..3c9e244da6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2143,6 +2143,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto scriptEngines = DependencyManager::get(); const auto testScript = property(hifi::properties::TEST).toUrl(); scriptEngines->loadScript(testScript, false); + + // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. + if (arguments().contains("--url")) { + auto reply = SandboxUtils::getStatus(); + connect(reply, &QNetworkReply::finished, this, [=] { + handleSandboxStatus(reply); + }); + } } else { PROFILE_RANGE(render, "GetSandboxStatus"); auto reply = SandboxUtils::getStatus(); From 5cbb8674ec2c001302cdcc43085b2ea7cf62157c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 14:45:28 -0700 Subject: [PATCH 099/174] Use default parameter for saveSnapshot(). --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 2 +- interface/src/ui/Snapshot.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22a77b9bf1..bd306948bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7387,7 +7387,7 @@ void Application::loadAvatarBrowser() const { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { // Get a screenshot and save it - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, QString()); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); // If we're not doing an animated snapshot as well... if (!includeAnimated) { // Tell the dependency manager that the capture of the still snapshot has taken place. diff --git a/interface/src/Application.h b/interface/src/Application.h index f1276bca34..fe31f55dcb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -732,6 +732,6 @@ private: std::atomic _pendingIdleEvent { true }; std::atomic _pendingRenderEvent { true }; - QString testSnapshotLocation { QString() }; + QString testSnapshotLocation; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 86c860cfcb..a3454bcba5 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -37,7 +37,7 @@ class Snapshot : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: - static QString saveSnapshot(QImage image, const QString& filename, const QString& pathname); + static QString saveSnapshot(QImage image, const QString& filename, const QString& pathname = QString()); static QTemporaryFile* saveTempSnapshot(QImage image); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); From e549f7b0859a69a6e48a915a9cf2537e9cf34991 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 2 May 2018 14:48:08 -0700 Subject: [PATCH 100/174] Fix VS2017 performance loss --- libraries/audio/src/AudioDynamics.h | 32 ++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index 03506fa8a1..542f6f1a05 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -21,7 +21,15 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) +#define FORCEINLINE __forceinline +#elif defined(__GNUC__) +#define FORCEINLINE inline __attribute__((always_inline)) +#else +#define FORCEINLINE inline +#endif + +#if defined(_MSC_VER) #include #define MUL64(a,b) __emul((a), (b)) #else @@ -42,14 +50,14 @@ #include // convert float to int using round-to-nearest -static inline int32_t floatToInt(float x) { +FORCEINLINE static int32_t floatToInt(float x) { return _mm_cvt_ss2si(_mm_load_ss(&x)); } #else // convert float to int using round-to-nearest -static inline int32_t floatToInt(float x) { +FORCEINLINE static int32_t floatToInt(float x) { x += (x < 0.0f ? -0.5f : 0.5f); // round return (int32_t)x; } @@ -60,12 +68,12 @@ static const double FIXQ31 = 2147483648.0; // convert float to Q31 static const double DB_TO_LOG2 = 0.16609640474436813; // convert dB to log2 // convert dB to amplitude -static inline double dBToGain(double dB) { +static double dBToGain(double dB) { return pow(10.0, dB / 20.0); } // convert milliseconds to first-order time constant -static inline int32_t msToTc(double ms, double sampleRate) { +static int32_t msToTc(double ms, double sampleRate) { double tc = exp(-1000.0 / (ms * sampleRate)); return (int32_t)(FIXQ31 * tc); // Q31 } @@ -144,7 +152,7 @@ static const int IEEE754_EXPN_BIAS = 127; // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff // x > 2^LOG2_HEADROOM undefined // -static inline int32_t peaklog2(float* input) { +FORCEINLINE static int32_t peaklog2(float* input) { // float as integer bits uint32_t u = *(uint32_t*)input; @@ -180,7 +188,7 @@ static inline int32_t peaklog2(float* input) { // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff // x > 2^LOG2_HEADROOM undefined // -static inline int32_t peaklog2(float* input0, float* input1) { +FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { // float as integer bits uint32_t u0 = *(uint32_t*)input0; @@ -219,7 +227,7 @@ static inline int32_t peaklog2(float* input0, float* input1) { // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff // x > 2^LOG2_HEADROOM undefined // -static inline int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) { +FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) { // float as integer bits uint32_t u0 = *(uint32_t*)input0; @@ -261,7 +269,7 @@ static inline int32_t peaklog2(float* input0, float* input1, float* input2, floa // Count Leading Zeros // Emulates the CLZ (ARM) and LZCNT (x86) instruction // -static inline int CLZ(uint32_t u) { +FORCEINLINE static int CLZ(uint32_t u) { if (u == 0) { return 32; @@ -294,7 +302,7 @@ static inline int CLZ(uint32_t u) { // Compute -log2(x) for x=[0,1] in Q31, result in Q26 // x <= 0 returns 0x7fffffff // -static inline int32_t fixlog2(int32_t x) { +FORCEINLINE static int32_t fixlog2(int32_t x) { if (x <= 0) { return 0x7fffffff; @@ -323,7 +331,7 @@ static inline int32_t fixlog2(int32_t x) { // Compute exp2(-x) for x=[0,32] in Q26, result in Q31 // x <= 0 returns 0x7fffffff // -static inline int32_t fixexp2(int32_t x) { +FORCEINLINE static int32_t fixexp2(int32_t x) { if (x <= 0) { return 0x7fffffff; @@ -349,7 +357,7 @@ static inline int32_t fixexp2(int32_t x) { } // fast TPDF dither in [-1.0f, 1.0f] -static inline float dither() { +FORCEINLINE static float dither() { static uint32_t rz = 0; rz = rz * 69069 + 1; int32_t r0 = rz & 0xffff; From 56e5b0e7b434c6375207c0f4cf14fbaea03666cb Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 15:25:31 -0700 Subject: [PATCH 101/174] Added `autoTester.enableAuto();` to the recursive tests. --- tools/auto-tester/src/Test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 7139f0a43c..18d1350402 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -371,7 +371,8 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact textStream << "var autoTester = Script.require(\"https://github.com/" + githubUser + "/hifi_tests/blob/" + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl; - textStream << "autoTester.enableRecursive();" << endl << endl; + textStream << "autoTester.enableRecursive();" << endl; + textStream << "autoTester.enableAuto();" << endl << endl; QVector testPathnames; From b9cdaf31a07b0346aa5e3a1005c106687097e1ef Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 15:26:03 -0700 Subject: [PATCH 102/174] Corrected name of create all recursive tests call. --- tools/auto-tester/src/ui/AutoTester.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index c5115d69b2..8c534eb7c7 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -95,7 +95,7 @@ 24 - + 360 From 5f394fb25442c51cf2bbbf8e39be2c26ddd0d588 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 2 May 2018 15:31:40 -0700 Subject: [PATCH 103/174] Remove workaround for VS2013 bug --- libraries/audio/src/AudioDynamics.h | 2 +- libraries/audio/src/AudioReverb.cpp | 2 +- libraries/audio/src/AudioSRC.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index 542f6f1a05..dac59dbce1 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -362,7 +362,7 @@ FORCEINLINE static float dither() { rz = rz * 69069 + 1; int32_t r0 = rz & 0xffff; int32_t r1 = rz >> 16; - return (int32_t)(r0 - r1) * (1/65536.0f); + return (r0 - r1) * (1/65536.0f); } // diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp index c561231376..0901e76251 100644 --- a/libraries/audio/src/AudioReverb.cpp +++ b/libraries/audio/src/AudioReverb.cpp @@ -1954,7 +1954,7 @@ static inline float dither() { rz = rz * 69069 + 1; int32_t r0 = rz & 0xffff; int32_t r1 = rz >> 16; - return (int32_t)(r0 - r1) * (1/65536.0f); + return (r0 - r1) * (1/65536.0f); } // convert float to int16_t with dither, interleave stereo diff --git a/libraries/audio/src/AudioSRC.cpp b/libraries/audio/src/AudioSRC.cpp index 80cb756d04..fbdf890246 100644 --- a/libraries/audio/src/AudioSRC.cpp +++ b/libraries/audio/src/AudioSRC.cpp @@ -1200,7 +1200,7 @@ static inline float dither() { rz = rz * 69069 + 1; int32_t r0 = rz & 0xffff; int32_t r1 = rz >> 16; - return (int32_t)(r0 - r1) * (1/65536.0f); + return (r0 - r1) * (1/65536.0f); } // convert float to int16_t with dither, interleave stereo From 3071b410bff9d1370077ecad1acb2cc6e38c58a6 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 2 May 2018 15:42:53 -0700 Subject: [PATCH 104/174] Remove obsolete 32-bit optimizations --- libraries/audio/src/AudioReverb.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp index 0901e76251..d457ce7a96 100644 --- a/libraries/audio/src/AudioReverb.cpp +++ b/libraries/audio/src/AudioReverb.cpp @@ -13,18 +13,11 @@ #include "AudioReverb.h" #ifdef _MSC_VER - #include -inline static int MULHI(int a, int b) { - long long c = __emul(a, b); - return ((int*)&c)[1]; -} - +#define MULHI(a,b) ((int32_t)(__emul(a, b) >> 32)) #else - -#define MULHI(a,b) (int)(((long long)(a) * (b)) >> 32) - -#endif // _MSC_VER +#define MULHI(a,b) ((int32_t)(((int64_t)(a) * (int64_t)(b)) >> 32)) +#endif #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) From 56ba59681a95450a151b6e9bad59a35e731c3380 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 2 May 2018 16:12:55 -0700 Subject: [PATCH 105/174] Fix MS14741, allowing uninstall of apps whose scripts are no longer running --- interface/src/commerce/QmlCommerce.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 568556cb22..722f29ba2f 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -301,7 +301,7 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { // Read from the file to know what .js script to stop QFile appFile(_appsPath + "/" + appHref.fileName()); if (!appFile.open(QIODevice::ReadOnly)) { - qCDebug(commerce) << "Couldn't open local .app.json file for deletion."; + qCDebug(commerce) << "Couldn't open local .app.json file for deletion. Cannot continue with app uninstallation. App filename is:" << appHref.fileName(); return false; } QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); @@ -309,15 +309,13 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { QString scriptUrl = appFileJsonObject["scriptURL"].toString(); if (!DependencyManager::get()->stopScript(scriptUrl.trimmed(), false)) { - qCDebug(commerce) << "Couldn't stop script."; - return false; + qCWarning(commerce) << "Couldn't stop script during app uninstall. Continuing anyway. ScriptURL is:" << scriptUrl.trimmed(); } // Delete the .app.json from the filesystem // remove() closes the file first. if (!appFile.remove()) { - qCDebug(commerce) << "Couldn't delete local .app.json file."; - return false; + qCWarning(commerce) << "Couldn't delete local .app.json file during app uninstall. Continuing anyway. App filename is:" << appHref.fileName(); } emit appUninstalled(itemHref); From e1c5eb9bda063367ab0af270d14505ab925af9ab Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 2 May 2018 17:17:19 -0700 Subject: [PATCH 106/174] Fix wizard wording --- domain-server/resources/web/wizard/index.shtml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/domain-server/resources/web/wizard/index.shtml b/domain-server/resources/web/wizard/index.shtml index 5a3286296d..3bc7503b44 100644 --- a/domain-server/resources/web/wizard/index.shtml +++ b/domain-server/resources/web/wizard/index.shtml @@ -26,7 +26,7 @@ Place names are similar to web addresses. Users who want to visit your domain can enter its Place Name in High Fidelity's Interface. You can choose a Place Name for your domain.
    - People can also use your domain's IP address (shown below) to visit your High Fidelity domain. + Your domain may also be reachable by IP address.
    @@ -35,10 +35,10 @@ From 3e77d946ea49e82fd1b22c3fbe0713aef57ac67b Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 2 May 2018 17:48:04 -0700 Subject: [PATCH 107/174] Silence warnings of unused functions --- libraries/audio/src/AudioDynamics.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index dac59dbce1..8dbc7a75cc 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -68,12 +68,12 @@ static const double FIXQ31 = 2147483648.0; // convert float to Q31 static const double DB_TO_LOG2 = 0.16609640474436813; // convert dB to log2 // convert dB to amplitude -static double dBToGain(double dB) { +FORCEINLINE static double dBToGain(double dB) { return pow(10.0, dB / 20.0); } // convert milliseconds to first-order time constant -static int32_t msToTc(double ms, double sampleRate) { +FORCEINLINE static int32_t msToTc(double ms, double sampleRate) { double tc = exp(-1000.0 / (ms * sampleRate)); return (int32_t)(FIXQ31 * tc); // Q31 } From 9776e1d15d42313d845ac532a4c77d807c1ae9fa Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 2 May 2018 23:38:30 -0700 Subject: [PATCH 108/174] Exposing larger number of ubo because we can and moving the ubo slot using 11 to 12 to avoid collision --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 4 ++-- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index b3a4a1a1ab..ee77646920 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,8 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static int32_t PARTICLE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 12 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { auto texturedPipeline = _texturedPipeline.lock(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 394ab08dfb..d571eac35c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -34,8 +34,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 12 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index f2e2271552..53a147fb27 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -92,7 +92,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 12; + static const int MAX_NUM_UNIFORM_BUFFERS = 15; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 31bbfdd708..7725ee7bce 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 12; +static const int MAX_NUM_UNIFORM_BUFFERS = 15; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From 2a7e8c6f89944962370edbbd310c4660f5738b3b Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 3 May 2018 07:15:18 -0700 Subject: [PATCH 109/174] Default audio meter overlay to "on" --- interface/src/ui/AvatarInputs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index 3053cb8855..0aa352de23 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -18,7 +18,7 @@ static AvatarInputs* INSTANCE{ nullptr }; -Setting::Handle showAudioToolsSetting { QStringList { "AvatarInputs", "showAudioTools" }, false }; +Setting::Handle showAudioToolsSetting { QStringList { "AvatarInputs", "showAudioTools" }, true }; AvatarInputs* AvatarInputs::getInstance() { if (!INSTANCE) { From 6579e3c3d23a9117e7f64bcc4a320bebf3498c7b Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 May 2018 09:09:58 -0700 Subject: [PATCH 110/174] Adjusting the number to 14 max UBO per shader stage after checking on opengl.glinfo.org --- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 53a147fb27..f0b79fb23e 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -92,7 +92,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 15; + static const int MAX_NUM_UNIFORM_BUFFERS = 14; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 7725ee7bce..4b965af7bc 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 15; +static const int MAX_NUM_UNIFORM_BUFFERS = 14; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From 60a49c3f7c630f03666e04cc67f3c4558c7816cf Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 May 2018 10:37:29 -0700 Subject: [PATCH 111/174] applying the local lights on translucent fix --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 4 ++-- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index b3a4a1a1ab..ee77646920 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,8 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static int32_t PARTICLE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 12 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { auto texturedPipeline = _texturedPipeline.lock(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 394ab08dfb..d571eac35c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -34,8 +34,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 12 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 5bbb44f9e1..314bbee387 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -91,7 +91,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 12; + static const int MAX_NUM_UNIFORM_BUFFERS = 14; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 84a7c275f0..90115806b4 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 12; +static const int MAX_NUM_UNIFORM_BUFFERS = 14; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From cefb8457eacb47af31b32f44088bd98e9b2c0edc Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 3 May 2018 11:17:31 -0700 Subject: [PATCH 112/174] Fix uninitialized boolean --- libraries/networking/src/NodeList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 9595c5da84..c5cf5e9524 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -167,7 +167,7 @@ private: HifiSockAddr _assignmentServerSocket; bool _isShuttingDown { false }; QTimer _keepAlivePingTimer; - bool _requestsDomainListData; + bool _requestsDomainListData { false }; mutable QReadWriteLock _ignoredSetLock; tbb::concurrent_unordered_set _ignoredNodeIDs; From 46f461dcdbdcf40095ef4e152fc082ae27d952e3 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 11:20:37 -0700 Subject: [PATCH 113/174] Don't display crash message if running from command line with a test script. --- interface/src/Application.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2abac520fb..45a1a34f1a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -743,6 +743,9 @@ extern DisplayPluginList getDisplayPlugins(); extern InputPluginList getInputPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); +const QString TEST_SCRIPT { "--testScript" }; +const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; + bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { const char** constArgv = const_cast(argv); @@ -777,7 +780,22 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset"; bool suppressPrompt = cmdOptionExists(argc, const_cast(argv), SUPPRESS_SETTINGS_RESET); - bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); + + // Ignore any previous crashes if running from command line with a test script. + bool inTestMode { false }; + for (int i = 0; i < argc; ++i) { + QString parameter(argv[i]); + if (parameter == TEST_SCRIPT) { + inTestMode = true; + break; + } + } + + bool previousSessionCrashed { false }; + if (!inTestMode) { + previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); + } + // get dir to use for cache static const auto CACHE_SWITCH = "--cache"; QString cacheDir = getCmdOption(argc, const_cast(argv), CACHE_SWITCH); @@ -997,10 +1015,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); { - const QString TEST_SCRIPT { "--testScript" }; - const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; - const QStringList args = arguments(); + for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT) { QString testScriptPath = args.at(i + 1); From 4793cddde6a4e1eb12281df57b0cb722e9e66f68 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 3 May 2018 11:27:07 -0700 Subject: [PATCH 114/174] fix highlighting issues --- .../highlightNearbyEntities.js | 4 ++- .../mouseHighlightEntities.js | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index a66f7bd144..32e1b4300d 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -89,7 +89,9 @@ } if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) { dispatcherUtils.highlightTargetEntity(props.id); - newHighlightedEntities.push(props.id); + if (newHighlightedEntities.indexOf(props.id) < 0) { + newHighlightedEntities.push(props.id); + } } } diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 6af1055a69..86c96fcf6b 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -12,7 +12,7 @@ /* jslint bitwise: true */ -/* global Script, print, Entities, Picks, HMD */ +/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar*/ (function() { @@ -20,6 +20,7 @@ function MouseHighlightEntities() { this.highlightedEntity = null; + this.grabbedEntity = null; this.parameters = dispatcherUtils.makeDispatcherModuleParameters( 5, @@ -27,13 +28,18 @@ [], 100); + this.setGrabbedEntity = function(entity) { + this.grabbedEntity = entity; + this.highlightedEntity = null; + }; + this.isReady = function(controllerData) { if (HMD.active) { if (this.highlightedEntity) { dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - } else { + } else if (!this.grabbedEntity) { var pickResult = controllerData.mouseRayPick; if (pickResult.type === Picks.INTERSECTED_ENTITY) { var targetEntityID = pickResult.objectID; @@ -70,8 +76,29 @@ var mouseHighlightEntities = new MouseHighlightEntities(); dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities); + var handleMessage = function(channel, message, sender) { + var data; + if (sender === MyAvatar.sessionUUID) { + if (channel === 'Hifi-Object-Manipulation') { + try { + data = JSON.parse(message); + if (data.action === 'grab') { + var grabbedEntity = data.grabbedEntity; + mouseHighlightEntities.setGrabbedEntity(grabbedEntity); + } else if (data.action === 'release') { + mouseHighlightEntities.setGrabbedEntity(null); + } + } catch (e) { + print("Warning: mouseHighlightEntities -- error parsing Hifi-Object-Manipulation: " + message); + } + } + } + }; + function cleanup() { dispatcherUtils.disableDispatcherModule("MouseHighlightEntities"); } + Messages.subscribe('Hifi-Object-Manipulation'); + Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); })(); From c258e8c2488b69f5b88846d9a09bb1a6bb3666dc Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 3 May 2018 11:27:07 -0700 Subject: [PATCH 115/174] fix highlighting issues --- .../highlightNearbyEntities.js | 4 ++- .../mouseHighlightEntities.js | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index a66f7bd144..32e1b4300d 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -89,7 +89,9 @@ } if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) { dispatcherUtils.highlightTargetEntity(props.id); - newHighlightedEntities.push(props.id); + if (newHighlightedEntities.indexOf(props.id) < 0) { + newHighlightedEntities.push(props.id); + } } } diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 6af1055a69..86c96fcf6b 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -12,7 +12,7 @@ /* jslint bitwise: true */ -/* global Script, print, Entities, Picks, HMD */ +/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar*/ (function() { @@ -20,6 +20,7 @@ function MouseHighlightEntities() { this.highlightedEntity = null; + this.grabbedEntity = null; this.parameters = dispatcherUtils.makeDispatcherModuleParameters( 5, @@ -27,13 +28,18 @@ [], 100); + this.setGrabbedEntity = function(entity) { + this.grabbedEntity = entity; + this.highlightedEntity = null; + }; + this.isReady = function(controllerData) { if (HMD.active) { if (this.highlightedEntity) { dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - } else { + } else if (!this.grabbedEntity) { var pickResult = controllerData.mouseRayPick; if (pickResult.type === Picks.INTERSECTED_ENTITY) { var targetEntityID = pickResult.objectID; @@ -70,8 +76,29 @@ var mouseHighlightEntities = new MouseHighlightEntities(); dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities); + var handleMessage = function(channel, message, sender) { + var data; + if (sender === MyAvatar.sessionUUID) { + if (channel === 'Hifi-Object-Manipulation') { + try { + data = JSON.parse(message); + if (data.action === 'grab') { + var grabbedEntity = data.grabbedEntity; + mouseHighlightEntities.setGrabbedEntity(grabbedEntity); + } else if (data.action === 'release') { + mouseHighlightEntities.setGrabbedEntity(null); + } + } catch (e) { + print("Warning: mouseHighlightEntities -- error parsing Hifi-Object-Manipulation: " + message); + } + } + } + }; + function cleanup() { dispatcherUtils.disableDispatcherModule("MouseHighlightEntities"); } + Messages.subscribe('Hifi-Object-Manipulation'); + Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); })(); From 767e6b15f34e9827d41f2e351933dba566eb0c2f Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 May 2018 11:42:06 -0700 Subject: [PATCH 116/174] Fixing the local lighting on translucents bug --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 4 ++-- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index b3a4a1a1ab..ee77646920 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,8 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static int32_t PARTICLE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 12 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { auto texturedPipeline = _texturedPipeline.lock(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 394ab08dfb..d571eac35c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -34,8 +34,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 12 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 5bbb44f9e1..314bbee387 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -91,7 +91,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 12; + static const int MAX_NUM_UNIFORM_BUFFERS = 14; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 84a7c275f0..90115806b4 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 12; +static const int MAX_NUM_UNIFORM_BUFFERS = 14; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From cffb008c3113b3871533d0e4b4aa1448dd99b604 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 3 May 2018 13:07:32 -0700 Subject: [PATCH 117/174] fixing edge case --- scripts/system/controllers/grab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 8ae94a4caa..a835373e4d 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -409,7 +409,7 @@ Grabber.prototype.pressEvent = function(event) { var args = "mouse"; Entities.callEntityMethod(this.entityID, "startDistanceGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ + Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'grab', grabbedEntity: this.entityID })); @@ -450,7 +450,7 @@ Grabber.prototype.releaseEvent = function(event) { var args = "mouse"; Entities.callEntityMethod(this.entityID, "releaseGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ + Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'release', grabbedEntity: this.entityID, joint: "mouse" From a6eab29b14fb952853462b5f37716cf4c9e6ee0a Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 3 May 2018 13:07:32 -0700 Subject: [PATCH 118/174] fixing edge case --- scripts/system/controllers/grab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 8ae94a4caa..a835373e4d 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -409,7 +409,7 @@ Grabber.prototype.pressEvent = function(event) { var args = "mouse"; Entities.callEntityMethod(this.entityID, "startDistanceGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ + Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'grab', grabbedEntity: this.entityID })); @@ -450,7 +450,7 @@ Grabber.prototype.releaseEvent = function(event) { var args = "mouse"; Entities.callEntityMethod(this.entityID, "releaseGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ + Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'release', grabbedEntity: this.entityID, joint: "mouse" From fc9bd7f905d2f0c6dd92ac539e2dbbb4afb75f17 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 3 May 2018 13:51:50 -0700 Subject: [PATCH 119/174] Fix for crash deep in QML after useFullAvatarURL Here we avoid calling FSTReader::downloadMapping() from within MyAvatar::useFullAvatarURL(). This prevents the error case where a QEventLoop is entered during QML execution. --- interface/src/avatar/MyAvatar.cpp | 18 +++++++++++------- .../src/model-networking/ModelCache.cpp | 19 +++++++++++-------- .../src/model-networking/ModelCache.h | 2 ++ 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e116b3830e..15b220c63b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1486,6 +1486,15 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { std::shared_ptr skeletonConnection = std::make_shared(); *skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() { if (skeletonModelChangeCount == _skeletonModelChangeCount) { + + if (_fullAvatarModelName.isEmpty()) { + // Store the FST file name into preferences + const auto& mapping = _skeletonModel->getGeometry()->getMapping(); + if (mapping.value("name").isValid()) { + _fullAvatarModelName = mapping.value("name").toString(); + } + } + initHeadBones(); _skeletonModel->setCauterizeBoneSet(_headBoneSet); _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); @@ -1548,12 +1557,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN if (_fullAvatarURLFromPreferences != fullAvatarURL) { _fullAvatarURLFromPreferences = fullAvatarURL; - if (modelName.isEmpty()) { - QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString()); - _fullAvatarModelName = fullAvatarFST["name"].toString(); - } else { - _fullAvatarModelName = modelName; - } + _fullAvatarModelName = modelName; } const QString& urlString = fullAvatarURL.toString(); @@ -1561,8 +1565,8 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN setSkeletonModelURL(fullAvatarURL); UserActivityLogger::getInstance().changedModel("skeleton", urlString); } + markIdentityDataChanged(); - } void MyAvatar::setAttachmentData(const QVector& attachmentData) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 416920d43f..45f2462f57 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -63,9 +63,10 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryMappingResource::downloadFinished", _url.toString(), { { "url", _url.toString() } }); - auto mapping = FSTReader::readMapping(data); + // store parsed contents of FST file + _mapping = FSTReader::readMapping(data); - QString filename = mapping.value("filename").toString(); + QString filename = _mapping.value("filename").toString(); if (filename.isNull()) { qCDebug(modelnetworking) << "Mapping file" << _url << "has no \"filename\" field"; @@ -73,7 +74,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { } else { QUrl url = _url.resolved(filename); - QString texdir = mapping.value(TEXDIR_FIELD).toString(); + QString texdir = _mapping.value(TEXDIR_FIELD).toString(); if (!texdir.isNull()) { if (!texdir.endsWith('/')) { texdir += '/'; @@ -83,15 +84,16 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { _textureBaseUrl = url.resolved(QUrl(".")); } - auto scripts = FSTReader::getScripts(_url, mapping); + auto scripts = FSTReader::getScripts(_url, _mapping); if (scripts.size() > 0) { - mapping.remove(SCRIPT_FIELD); + _mapping.remove(SCRIPT_FIELD); for (auto &scriptPath : scripts) { - mapping.insertMulti(SCRIPT_FIELD, scriptPath); + _mapping.insertMulti(SCRIPT_FIELD, scriptPath); } } - auto animGraphVariant = mapping.value("animGraphUrl"); + auto animGraphVariant = _mapping.value("animGraphUrl"); + if (animGraphVariant.isValid()) { QUrl fstUrl(animGraphVariant.toString()); if (fstUrl.isValid()) { @@ -104,7 +106,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { } auto modelCache = DependencyManager::get(); - GeometryExtra extra{ mapping, _textureBaseUrl, false }; + GeometryExtra extra{ _mapping, _textureBaseUrl, false }; // Get the raw GeometryResource _geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast(); @@ -379,6 +381,7 @@ Geometry::Geometry(const Geometry& geometry) { } _animGraphOverrideUrl = geometry._animGraphOverrideUrl; + _mapping = geometry._mapping; } void Geometry::setTextures(const QVariantMap& textureMap) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index cda825e5fb..7cb11587c9 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -55,6 +55,7 @@ public: virtual bool areTexturesLoaded() const; const QUrl& getAnimGraphOverrideUrl() const { return _animGraphOverrideUrl; } + const QVariantHash& getMapping() const { return _mapping; } protected: friend class GeometryMappingResource; @@ -68,6 +69,7 @@ protected: NetworkMaterials _materials; QUrl _animGraphOverrideUrl; + QVariantHash _mapping; // parsed contents of FST file. private: mutable bool _areTexturesLoaded { false }; From 3a5425122bcba2a91525c457ef92ca752a4dd782 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 14:31:01 -0700 Subject: [PATCH 120/174] Shutdown interface when test script finishes. --- interface/src/Application.cpp | 4 +++- libraries/script-engine/src/ScriptEngines.cpp | 11 ++++++++++- libraries/script-engine/src/ScriptEngines.h | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 45a1a34f1a..d8c162a79c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2160,7 +2160,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (testProperty.isValid()) { auto scriptEngines = DependencyManager::get(); const auto testScript = property(hifi::properties::TEST).toUrl(); - scriptEngines->loadScript(testScript, false); + + // Set last parameter to exit interface when the test script finishes + scriptEngines->loadScript(testScript, false, false, false, false, true); // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. if (arguments().contains("--url")) { diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index f2ed296b63..ef4eddbf39 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -456,7 +456,7 @@ void ScriptEngines::reloadAllScripts() { } ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, - bool activateMainWindow, bool reload) { + bool activateMainWindow, bool reload, bool exitWhenFinished) { if (thread() != QThread::currentThread()) { ScriptEnginePointer result { nullptr }; BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEnginePointer, result), @@ -496,6 +496,11 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); + // Shutdown interface when script finishes, if requested + if (exitWhenFinished) { + connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::exitWhenFinished); + } + // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl, reload); } @@ -536,6 +541,10 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { emit scriptCountChanged(); } +void ScriptEngines::exitWhenFinished() { + qApp->quit(); +} + int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 376bae4827..6f88e8978d 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -91,7 +91,7 @@ public: * @returns {boolean} */ Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(), - bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false); + bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool exitWhenFinished = false); /**jsdoc * @function ScriptDiscoveryService.stopScript @@ -266,6 +266,7 @@ protected: ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); + void exitWhenFinished(); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEnginePointer); From 3b566332c6d6fe3413b0bf6b3293dd75b46a8e01 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 14:34:12 -0700 Subject: [PATCH 121/174] Shutdown interface when test script finishes. --- libraries/script-engine/src/ScriptEngines.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index ef4eddbf39..d2834e8c4a 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -456,7 +456,7 @@ void ScriptEngines::reloadAllScripts() { } ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, - bool activateMainWindow, bool reload, bool exitWhenFinished) { + bool activateMainWindow, bool reload, bool exitWhenFinished) { if (thread() != QThread::currentThread()) { ScriptEnginePointer result { nullptr }; BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEnginePointer, result), @@ -496,7 +496,7 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); - // Shutdown interface when script finishes, if requested + // Shutdown Interface when script finishes, if requested if (exitWhenFinished) { connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::exitWhenFinished); } From beb19c53faa18ff57bb0f12b147b2ca5292354e6 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 15:00:14 -0700 Subject: [PATCH 122/174] Added date and time to auto-generated scripts. --- tools/auto-tester/src/Test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 18d1350402..e9dcad6c72 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -366,10 +366,10 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } QTextStream textStream(&allTestsFilename); - textStream << "// This is an automatically generated file, created by auto-tester" << endl << endl; + textStream << "// This is an automatically generated file, created by auto-tester on " << __DATE__ << ", " << __TIME__ << endl << endl; textStream << "var autoTester = Script.require(\"https://github.com/" + githubUser + "/hifi_tests/blob/" - + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl; + + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl << endl; textStream << "autoTester.enableRecursive();" << endl; textStream << "autoTester.enableAuto();" << endl << endl; From fe9c6052f73a55aa1873485fa6ae6a7c1d6bf580 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 15:02:11 -0700 Subject: [PATCH 123/174] Added `quitWhenFinished` parameter to the command line. --- interface/src/Application.cpp | 15 +++++++++++---- interface/src/Application.h | 1 + interface/src/ui/Snapshot.cpp | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8c162a79c..fed6caab89 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -743,7 +743,9 @@ extern DisplayPluginList getDisplayPlugins(); extern InputPluginList getInputPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); +// Parameters used for running tests from teh command line const QString TEST_SCRIPT { "--testScript" }; +const QString TEST_QUIT_WHEN_FINISHED { "--quitWhenFinished" }; const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { @@ -1018,11 +1020,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { - if (args.at(i) == TEST_SCRIPT) { + if (args.at(i) == TEST_SCRIPT && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); - } + } + + // quite when finished parameter must directly follow the test script + if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED) { + quitWhenFinished = true; + } } else if (args.at(i) == TEST_SNAPSHOT_LOCATION) { // Set test snapshot location only if it is a writeable directory QString pathname(args.at(i + 1)); @@ -2161,8 +2168,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto scriptEngines = DependencyManager::get(); const auto testScript = property(hifi::properties::TEST).toUrl(); - // Set last parameter to exit interface when the test script finishes - scriptEngines->loadScript(testScript, false, false, false, false, true); + // Set last parameter to exit interface when the test script finishes, if so requested + scriptEngines->loadScript(testScript, false, false, false, false, quitWhenFinished); // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. if (arguments().contains("--url")) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 088b74aa9b..cc366c74fe 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -740,5 +740,6 @@ private: std::atomic _pendingRenderEvent { true }; QString testSnapshotLocation; + bool quitWhenFinished { false }; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index d52f01223c..5616b35ac0 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -73,6 +73,7 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { return data; } +#pragma optimize("", off) QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) { QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname); @@ -92,6 +93,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } +#pragma optimize("", off) QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { // adding URL to snapshot From 2c6c0a25fcc95b0ba37a356ae460d3da8b796036 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 15:15:30 -0700 Subject: [PATCH 124/174] Add testSnapshotLocation parameter to `takeSnapshot`. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fed6caab89..54f1ba2606 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7412,7 +7412,7 @@ void Application::loadAvatarBrowser() const { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { // Get a screenshot and save it - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, testSnapshotLocation); // If we're not doing an animated snapshot as well... if (!includeAnimated) { // Tell the dependency manager that the capture of the still snapshot has taken place. From 887b8285cdc03dce6c9ab369e6f8200ed16668bf Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 16:44:04 -0700 Subject: [PATCH 125/174] Removed unneeded pragma. --- interface/src/ui/Snapshot.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 5616b35ac0..a84e19154b 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -73,7 +73,6 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { return data; } -#pragma optimize("", off) QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) { QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname); From da621d99d35c55fae647d2f4510b985f21b218d1 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 16:52:03 -0700 Subject: [PATCH 126/174] Removed unneeded pragma. --- interface/src/ui/Snapshot.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index a84e19154b..d52f01223c 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -92,7 +92,6 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } -#pragma optimize("", off) QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { // adding URL to snapshot From 1f691edf0d7a731a692757844748c62a9e62a088 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 17:04:17 -0700 Subject: [PATCH 127/174] Removed platform code (was used for MD files). --- tools/auto-tester/src/Test.cpp | 72 ---------------------------------- tools/auto-tester/src/Test.h | 6 --- 2 files changed, 78 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index e9dcad6c72..e00bc920e5 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -530,26 +530,6 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { QStringList tokens = line.split('"'); relevantTextFromTest.title = tokens[1]; - } else if (lineAssertPlatform.match(line).hasMatch()) { - QStringList platforms = line.split('"'); - relevantTextFromTest.platform = platforms[1]; - - } else if (lineAssertDisplay.match(line).hasMatch()) { - QStringList displays = line.split('"'); - relevantTextFromTest.display = displays[1]; - - } else if (lineAssertCPU.match(line).hasMatch()) { - QStringList cpus = line.split('"'); - relevantTextFromTest.cpu = cpus[1]; - - } else if (lineAssertGPU.match(line).hasMatch()) { - QStringList gpus = line.split('"'); - relevantTextFromTest.gpu = gpus[1]; - - } else if (lineAssertPhysicalMemoryGB.match(line).hasMatch()) { - QStringList physicalMemoryGB = line.split('"'); - relevantTextFromTest.physicalMemoryGB = physicalMemoryGB[1]; - } else if (lineStepSnapshot.match(line).hasMatch()) { QStringList tokens = line.split('"'); QString nameOfStep = tokens[1]; @@ -653,58 +633,6 @@ void Test::createMDFile(const QString& testDirectory) { stream << "## Preconditions" << "\n"; stream << "- In an empty region of a domain with editing rights." << "\n\n"; - // Platform - QStringList platforms = testScriptLines.platform.split(" ");; - if (platforms.size() > 0) { - stream << "## Platforms\n"; - stream << "Run the test on each of the following platforms\n"; - for (int i = 0; i < platforms.size(); ++i) { - // Note that the platforms parameter may include extra spaces, these appear as empty strings in the list - if (platforms[i] != QString()) { - stream << " - " << platforms[i] << "\n"; - } - } - } - - // Display - QStringList displays = testScriptLines.display.split(" "); - if (displays.size()) { - stream << "## Displays\n"; - stream << "Run the test on each of the following displays\n"; - for (int i = 0; i < displays.size(); ++i) { - // Note that the displays parameter may include extra spaces, these appear as empty strings in the list - if (displays[i] != QString()) { - stream << " - " << displays[i] << "\n"; - } - } - } - - // CPU - QStringList cpus = testScriptLines.cpu.split(" "); - if (cpus.size() > 0) { - stream << "## Processors\n"; - stream << "Run the test on each of the following processors\n"; - for (int i = 0; i < cpus.size(); ++i) { - // Note that the cpus parameter may include extra spaces, these appear as empty strings in the list - if (cpus[i] != QString()) { - stream << " - " << cpus[i] << "\n"; - } - } - } - - // GPU - QStringList gpus = testScriptLines.gpu.split(" "); - if (gpus.size() > 0) { - stream << "## Graphics Cards\n"; - stream << "Run the test on graphics cards from each of the following vendors\n"; - for (int i = 0; i < gpus.size(); ++i) { - // Note that the gpus parameter may include extra spaces, these appear as empty strings in the list - if (gpus[i] != QString()) { - stream << " - " << gpus[i] << "\n"; - } - } - } - stream << "## Steps\n"; stream << "Press space bar to advance step by step\n\n"; diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 02cab53381..b341c1d00f 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -30,12 +30,6 @@ using StepList = std::vector; class ExtractedText { public: QString title; - QString platform; - QString display; - QString cpu; - QString gpu; - QString physicalMemoryGB; - StepList stepList; }; From 7fe16f82fbdaed268b03ce8caa935b196019c929 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 3 May 2018 17:08:17 -0700 Subject: [PATCH 128/174] Move variables to Agent.cpp --- assignment-client/src/Agent.cpp | 3 +++ libraries/avatars/src/AvatarData.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f560ea72bd..0b373e511b 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -554,6 +554,9 @@ void Agent::setIsAvatar(bool isAvatar) { connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket); connect(_avatarViewTimer, &QTimer::timeout, this, &Agent::sendAvatarViewFrustum); + static const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; + static const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 1000; + // start the timers _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets _avatarViewTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 3db94f6691..bbcdd3693d 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -277,9 +277,6 @@ namespace AvatarDataPacket { const float MAX_AUDIO_LOUDNESS = 1000.0f; // close enough for mouth animation -const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; -const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 100; - // See also static AvatarData::defaultFullAvatarModelUrl(). const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default"); From 79576e0f48f9dd7b080d333d9d4b5113853e89e7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 3 May 2018 17:16:35 -0700 Subject: [PATCH 129/174] update request and dependency hoek for CVE --- server-console/package-lock.json | 355 +++++++++++++------------------ server-console/package.json | 2 +- 2 files changed, 147 insertions(+), 210 deletions(-) diff --git a/server-console/package-lock.json b/server-console/package-lock.json index 4311fde51a..4f12f2fa00 100644 --- a/server-console/package-lock.json +++ b/server-console/package-lock.json @@ -20,7 +20,6 @@ "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.0.0", @@ -41,11 +40,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=" }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, "array-find-index": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.1.tgz", @@ -118,16 +112,10 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "author-regex": { "version": "1.0.0", @@ -136,17 +124,14 @@ "dev": true }, "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.3.2.tgz", - "integrity": "sha1-054L7kEs7Q6O2Uoj4xTzE6lbn9E=", - "requires": { - "lru-cache": "4.0.1" - } + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" }, "base64-js": { "version": "1.2.0", @@ -204,11 +189,11 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "requires": { - "hoek": "2.16.3" + "hoek": "4.2.1" } }, "buffers": { @@ -239,9 +224,9 @@ } }, "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chainsaw": { "version": "0.1.0", @@ -252,18 +237,6 @@ "traverse": "0.3.9" } }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, "cheerio": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", @@ -295,8 +268,7 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.0.0", @@ -318,6 +290,7 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, "requires": { "graceful-readlink": "1.0.1" } @@ -373,11 +346,21 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "requires": { - "boom": "2.10.1" + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } } }, "css-select": { @@ -728,7 +711,7 @@ "minimist": "1.2.0", "pretty-bytes": "1.0.4", "progress-stream": "1.2.0", - "request": "2.71.0", + "request": "2.85.0", "single-line-log": "1.1.2", "throttleit": "0.0.2" }, @@ -828,11 +811,6 @@ "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, "extend": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", @@ -875,14 +853,12 @@ "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fd-slicer": { "version": "1.0.1", @@ -976,13 +952,23 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "1.0.0-rc4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", - "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "async": "1.5.2", - "combined-stream": "1.0.5", - "mime-types": "2.1.10" + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + } } }, "fs-extra": { @@ -1058,19 +1044,6 @@ } } }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "requires": { - "is-property": "1.0.2" - } - }, "get-package-info": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz", @@ -1212,7 +1185,8 @@ "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true }, "growly": { "version": "1.3.0", @@ -1222,43 +1196,32 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "chalk": "1.1.3", - "commander": "2.9.0", - "is-my-json-valid": "2.13.1", - "pinkie-promise": "2.0.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" } }, "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "home-path": { "version": "1.0.5", @@ -1301,13 +1264,20 @@ } }, "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "0.2.0", + "assert-plus": "1.0.0", "jsprim": "1.2.2", "sshpk": "1.7.4" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } } }, "indent-string": { @@ -1388,28 +1358,12 @@ "number-is-nan": "1.0.0" } }, - "is-my-json-valid": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", - "integrity": "sha1-1Vd4qC/rawlj/0vhEdXRaE6JBwc=", - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "2.0.0", - "xtend": "4.0.1" - } - }, "is-promise": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -1465,8 +1419,7 @@ "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "json-stringify-safe": { "version": "5.0.1", @@ -1478,11 +1431,6 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.2.3.tgz", "integrity": "sha1-4lK5mmr5AdPsQfMyWJyQUJp7xgU=" }, - "jsonpointer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz", - "integrity": "sha1-OvHdIP6FRjkQ1GmjheMwF9KgMNk=" - }, "jsprim": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz", @@ -1569,15 +1517,6 @@ "signal-exit": "2.1.2" } }, - "lru-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", - "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.0.0" - } - }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -1603,16 +1542,16 @@ } }, "mime-db": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz", - "integrity": "sha1-qyOmNy3J2G09yRIb0OvTgQWhkEo=" + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" }, "mime-types": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz", - "integrity": "sha1-uTx8tDYuFtQQcqflRTj7TUMHCDc=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "requires": { - "mime-db": "1.22.0" + "mime-db": "1.33.0" } }, "minimist": { @@ -1891,11 +1830,6 @@ } } }, - "node-uuid": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", - "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=" - }, "nodeify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", @@ -1945,7 +1879,7 @@ "minimist": "1.2.0", "pretty-bytes": "1.0.4", "progress-stream": "1.2.0", - "request": "2.71.0", + "request": "2.85.0", "single-line-log": "1.1.2", "throttleit": "0.0.2" }, @@ -1973,9 +1907,9 @@ "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=" }, "oauth-sign": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz", - "integrity": "sha1-GCQ5vbkTeL90YOdcZOpD5kSN7wY=" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.0.1", @@ -2099,8 +2033,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "2.3.0", @@ -2111,12 +2044,14 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, "requires": { "pinkie": "2.0.4" } @@ -2166,11 +2101,6 @@ "is-promise": "1.0.1" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, "pump": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.1.tgz", @@ -2183,8 +2113,7 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "q": { "version": "1.5.1", @@ -2193,9 +2122,9 @@ "dev": true }, "qs": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.1.0.tgz", - "integrity": "sha1-7B0WJrJCeNmfD99FSeUk4k7O6yY=" + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "rc": { "version": "1.1.6", @@ -2252,31 +2181,39 @@ } }, "request": { - "version": "2.71.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.71.0.tgz", - "integrity": "sha1-bxRkPJxaZ8ruapXPjvBHfVYDvZE=", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.3.2", - "bl": "1.1.2", - "caseless": "0.11.0", + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", "combined-stream": "1.0.5", - "extend": "3.0.0", + "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "1.0.0-rc4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.10", - "node-uuid": "1.4.7", - "oauth-sign": "0.8.1", - "qs": "6.1.0", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.2.2", - "tunnel-agent": "0.4.2" + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + }, + "dependencies": { + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + } } }, "request-progress": { @@ -2308,8 +2245,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "sanitize-filename": { "version": "1.6.1", @@ -2347,11 +2283,11 @@ } }, "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "requires": { - "hoek": "2.16.3" + "hoek": "4.2.1" } }, "spdx-correct": { @@ -2483,11 +2419,6 @@ } } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, "tar-fs": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.12.0.tgz", @@ -2585,9 +2516,12 @@ } }, "tough-cookie": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz", - "integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc=" + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } }, "traverse": { "version": "0.3.9", @@ -2611,9 +2545,12 @@ } }, "tunnel-agent": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz", - "integrity": "sha1-EQTj82rIcSXChycAZ9WC0YEzv+4=" + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } }, "tweetnacl": { "version": "0.14.3", @@ -2644,6 +2581,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", @@ -2710,11 +2652,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, - "yallist": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", - "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=" - }, "yargs": { "version": "3.32.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", diff --git a/server-console/package.json b/server-console/package.json index 2428d2574e..6dd39ea6f8 100644 --- a/server-console/package.json +++ b/server-console/package.json @@ -30,7 +30,7 @@ "fs-extra": "^1.0.0", "node-notifier": "^5.2.1", "os-homedir": "^1.0.1", - "request": "^2.67.0", + "request": "^2.85.0", "request-progress": "1.0.2", "tar-fs": "^1.12.0", "yargs": "^3.30.0" From d774dc2060e546612526cf7df7877ee39ad87812 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 26 Apr 2018 18:34:38 -0700 Subject: [PATCH 130/174] WIP Only use conical frustums on the server --- .../src/entities/EntityPriorityQueue.cpp | 76 -------- .../src/entities/EntityTreeSendThread.cpp | 87 ++------- .../src/entities/EntityTreeSendThread.h | 4 +- libraries/entities/src/DiffTraversal.cpp | 179 ++++++++---------- libraries/entities/src/DiffTraversal.h | 14 +- .../entities/src}/EntityPriorityQueue.h | 38 +--- libraries/shared/src/GLMHelpers.cpp | 6 + libraries/shared/src/GLMHelpers.h | 2 + libraries/shared/src/ViewFrustum.cpp | 7 - .../shared/src/shared/ConicalViewFrustum.cpp | 125 ++++++++++++ .../shared/src/shared/ConicalViewFrustum.h | 64 +++++++ 11 files changed, 306 insertions(+), 296 deletions(-) delete mode 100644 assignment-client/src/entities/EntityPriorityQueue.cpp rename {assignment-client/src/entities => libraries/entities/src}/EntityPriorityQueue.h (70%) create mode 100644 libraries/shared/src/shared/ConicalViewFrustum.cpp create mode 100644 libraries/shared/src/shared/ConicalViewFrustum.h diff --git a/assignment-client/src/entities/EntityPriorityQueue.cpp b/assignment-client/src/entities/EntityPriorityQueue.cpp deleted file mode 100644 index 88dee58f9d..0000000000 --- a/assignment-client/src/entities/EntityPriorityQueue.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// EntityPriorityQueue.cpp -// assignment-client/src/entities -// -// Created by Andrew Meadows 2017.08.08 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "EntityPriorityQueue.h" - -const float PrioritizedEntity::DO_NOT_SEND = -1.0e-6f; -const float PrioritizedEntity::FORCE_REMOVE = -1.0e-5f; -const float PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY = 1.0f; - -void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) { - // The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part. - // Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum. - _position = viewFrustum.getPosition(); - _direction = viewFrustum.getDirection(); - - // We cache the sin and cos of the half angle of the cone that bounds the frustum. - // (the math here is left as an exercise for the reader) - float A = viewFrustum.getAspectRatio(); - float t = tanf(0.5f * viewFrustum.getFieldOfView()); - _cosAngle = 1.0f / sqrtf(1.0f + (A * A + 1.0f) * (t * t)); - _sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle); - - _radius = viewFrustum.getCenterRadius(); -} - -float ConicalViewFrustum::computePriority(const AACube& cube) const { - glm::vec3 p = cube.calcCenter() - _position; // position of bounding sphere in view-frame - float d = glm::length(p); // distance to center of bounding sphere - float r = 0.5f * cube.getScale(); // radius of bounding sphere - if (d < _radius + r) { - return r; - } - // We check the angle between the center of the cube and the _direction of the view. - // If it is less than the sum of the half-angle from center of cone to outer edge plus - // the half apparent angle of the bounding sphere then it is in view. - // - // The math here is left as an exercise for the reader with the following hints: - // (1) We actually check the dot product of the cube's local position rather than the angle and - // (2) we take advantage of this trig identity: cos(A+B) = cos(A)*cos(B) - sin(A)*sin(B) - if (glm::dot(p, _direction) > sqrtf(d * d - r * r) * _cosAngle - r * _sinAngle) { - const float AVOID_DIVIDE_BY_ZERO = 0.001f; - return r / (d + AVOID_DIVIDE_BY_ZERO); - } - return PrioritizedEntity::DO_NOT_SEND; -} - - -void ConicalView::set(const DiffTraversal::View& view) { - auto size = view.viewFrustums.size(); - _conicalViewFrustums.resize(size); - for (size_t i = 0; i < size; ++i) { - _conicalViewFrustums[i].set(view.viewFrustums[i]); - } -} - -float ConicalView::computePriority(const AACube& cube) const { - if (_conicalViewFrustums.empty()) { - return PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; - } - - float priority = PrioritizedEntity::DO_NOT_SEND; - - for (const auto& view : _conicalViewFrustums) { - priority = std::max(priority, view.computePriority(cube)); - } - - return priority; -} diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 2e57f2e00f..0d943055f4 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -141,16 +141,8 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O if (forceRemove) { priority = PrioritizedEntity::FORCE_REMOVE; } else { - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - const auto& view = _traversal.getCurrentView(); - if (view.intersects(cube) && view.isBigEnough(cube)) { - priority = _conicalView.computePriority(cube); - } - } else { - priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; - } + const auto& view = _traversal.getCurrentView(); + priority = view.computePriority(entity); } if (priority != PrioritizedEntity::DO_NOT_SEND) { @@ -235,11 +227,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En // (3) Differential = view has changed --> find what has changed or in new view but not old // // The "scanCallback" we provide to the traversal depends on the type: - // - // The _conicalView is updated here as a cached view approximation used by the lambdas for efficient - // computation of entity sorting priorities. - // - _conicalView.set(_traversal.getCurrentView()); switch (type) { case DiffTraversal::First: @@ -251,25 +238,8 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En if (_sendQueue.contains(entity.get())) { return; } - float priority = PrioritizedEntity::DO_NOT_SEND; - - - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - const auto& view = _traversal.getCurrentView(); - // Check the size of the entity, it's possible that a "too small to see" entity is included in a - // larger octree cell because of its position (for example if it crosses the boundary of a cell it - // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen - // before we consider including it. - if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && - view.isBigEnough(cube)) { - priority = _conicalView.computePriority(cube); - } - } else { - priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; - } - + const auto& view = _traversal.getCurrentView(); + float priority = view.computePriority(entity); if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority); @@ -288,21 +258,11 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En } float priority = PrioritizedEntity::DO_NOT_SEND; - auto knownTimestamp = _knownState.find(entity.get()); if (knownTimestamp == _knownState.end()) { - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - const auto& view = _traversal.getCurrentView(); - // See the DiffTraversal::First case for an explanation of the "entity is too small" check - if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && - view.isBigEnough(cube)) { - priority = _conicalView.computePriority(cube); - } - } else { - priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; - } + const auto& view = _traversal.getCurrentView(); + priority = view.computePriority(entity); + } else if (entity->getLastEdited() > knownTimestamp->second || entity->getLastChangedOnServer() > knownTimestamp->second) { // it is known and it changed --> put it on the queue with any priority @@ -310,7 +270,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } - if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority); } @@ -328,21 +287,11 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En } float priority = PrioritizedEntity::DO_NOT_SEND; - auto knownTimestamp = _knownState.find(entity.get()); if (knownTimestamp == _knownState.end()) { - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - const auto& view = _traversal.getCurrentView(); - // See the DiffTraversal::First case for an explanation of the "entity is too small" check - if ((next.intersection == ViewFrustum::INSIDE || view.intersects(cube)) && - view.isBigEnough(cube)) { - priority = _conicalView.computePriority(cube); - } - } else { - priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; - } + const auto& view = _traversal.getCurrentView(); + priority = view.computePriority(entity); + } else if (entity->getLastEdited() > knownTimestamp->second || entity->getLastChangedOnServer() > knownTimestamp->second) { // it is known and it changed --> put it on the queue with any priority @@ -350,7 +299,6 @@ void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, En priority = PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; } - if (priority != PrioritizedEntity::DO_NOT_SEND) { _sendQueue.emplace(entity, priority); } @@ -463,14 +411,13 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream void EntityTreeSendThread::editingEntityPointer(const EntityItemPointer& entity) { if (entity) { if (!_sendQueue.contains(entity.get()) && _knownState.find(entity.get()) != _knownState.end()) { - bool success = false; - AACube cube = entity->getQueryAACube(success); - if (success) { - // We can force a removal from _knownState if the current view is used and entity is out of view - if (_traversal.doesCurrentUseViewFrustum() && !_traversal.getCurrentView().intersects(cube)) { - _sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true); - } - } else { + const auto& view = _traversal.getCurrentView(); + float priority = view.computePriority(entity); + + // We can force a removal from _knownState if the current view is used and entity is out of view + if (priority == PrioritizedEntity::DO_NOT_SEND) { + _sendQueue.emplace(entity, PrioritizedEntity::FORCE_REMOVE, true); + } else if (priority == PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY) { _sendQueue.emplace(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY, true); } } diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 9eea98b7fd..1305d7bfc7 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -17,8 +17,9 @@ #include "../octree/OctreeSendThread.h" #include +#include +#include -#include "EntityPriorityQueue.h" class EntityNodeData; class EntityItem; @@ -51,7 +52,6 @@ private: DiffTraversal _traversal; EntityPriorityQueue _sendQueue; std::unordered_map _knownState; - ConicalView _conicalView; // cached optimized view for fast priority calculations // packet construction stuff EntityTreeElementExtraEncodeDataPointer _extraEncodeData { new EntityTreeElementExtraEncodeData() }; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 39328e11ad..36d1f41267 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -13,6 +13,8 @@ #include +#include "EntityPriorityQueue.h" + DiffTraversal::Waypoint::Waypoint(EntityTreeElementPointer& element) : _nextIndex(0) { assert(element); _weakElement = element; @@ -35,19 +37,9 @@ void DiffTraversal::Waypoint::getNextVisibleElementFirstTime(DiffTraversal::Visi while (_nextIndex < NUMBER_OF_CHILDREN) { EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex); ++_nextIndex; - if (nextElement) { - const auto& cube = nextElement->getAACube(); - if (!view.usesViewFrustums()) { - // No LOD truncation if we aren't using the view frustum - next.element = nextElement; - return; - } else if (view.intersects(cube)) { - // check for LOD truncation - if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) { - next.element = nextElement; - return; - } - } + if (nextElement && view.shouldTraverseElement(*nextElement)) { + next.element = nextElement; + return; } } } @@ -63,7 +55,6 @@ void DiffTraversal::Waypoint::getNextVisibleElementRepeat( EntityTreeElementPointer element = _weakElement.lock(); if (element->getLastChangedContent() > lastTime) { next.element = element; - next.intersection = ViewFrustum::INTERSECT; return; } } @@ -73,30 +64,17 @@ void DiffTraversal::Waypoint::getNextVisibleElementRepeat( while (_nextIndex < NUMBER_OF_CHILDREN) { EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex); ++_nextIndex; - if (nextElement && nextElement->getLastChanged() > lastTime) { - if (!view.usesViewFrustums()) { - // No LOD truncation if we aren't using the view frustum - next.element = nextElement; - next.intersection = ViewFrustum::INSIDE; - return; - } else { - // check for LOD truncation - const auto& cube = nextElement->getAACube(); - if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) { - ViewFrustum::intersection intersection = view.calculateIntersection(cube); - if (intersection != ViewFrustum::OUTSIDE) { - next.element = nextElement; - next.intersection = intersection; - return; - } - } - } + if (nextElement && + nextElement->getLastChanged() > lastTime && + view.shouldTraverseElement(*nextElement)) { + + next.element = nextElement; + return; } } } } next.element.reset(); - next.intersection = ViewFrustum::OUTSIDE; } void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::VisibleElement& next, @@ -106,7 +84,6 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V ++_nextIndex; EntityTreeElementPointer element = _weakElement.lock(); next.element = element; - next.intersection = ViewFrustum::INTERSECT; return; } else if (_nextIndex < NUMBER_OF_CHILDREN) { EntityTreeElementPointer element = _weakElement.lock(); @@ -114,74 +91,14 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V while (_nextIndex < NUMBER_OF_CHILDREN) { EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex); ++_nextIndex; - if (nextElement) { - // check for LOD truncation - const auto& cube = nextElement->getAACube(); - if (view.isBigEnough(cube, MIN_ELEMENT_ANGULAR_DIAMETER)) { - ViewFrustum::intersection intersection = view.calculateIntersection(cube); - if (intersection != ViewFrustum::OUTSIDE) { - next.element = nextElement; - next.intersection = intersection; - return; - } - } + if (nextElement && view.shouldTraverseElement(*nextElement)) { + next.element = nextElement; + return; } } } } next.element.reset(); - next.intersection = ViewFrustum::OUTSIDE; -} - -bool DiffTraversal::View::isBigEnough(const AACube& cube, float minDiameter) const { - if (viewFrustums.empty()) { - // Everything is big enough when not using view frustums - return true; - } - - bool isBigEnough = std::any_of(std::begin(viewFrustums), std::end(viewFrustums), - [&](const ViewFrustum& viewFrustum) { - return isAngularSizeBigEnough(viewFrustum.getPosition(), cube, lodScaleFactor, minDiameter); - }); - - return isBigEnough; -} - -bool DiffTraversal::View::intersects(const AACube& cube) const { - if (viewFrustums.empty()) { - // Everything intersects when not using view frustums - return true; - } - - bool intersects = std::any_of(std::begin(viewFrustums), std::end(viewFrustums), - [&](const ViewFrustum& viewFrustum) { - return viewFrustum.cubeIntersectsKeyhole(cube); - }); - - return intersects; -} - -ViewFrustum::intersection DiffTraversal::View::calculateIntersection(const AACube& cube) const { - if (viewFrustums.empty()) { - // Everything is inside when not using view frustums - return ViewFrustum::INSIDE; - } - - ViewFrustum::intersection intersection = ViewFrustum::OUTSIDE; - - for (const auto& viewFrustum : viewFrustums) { - switch (viewFrustum.calculateCubeKeyholeIntersection(cube)) { - case ViewFrustum::INSIDE: - return ViewFrustum::INSIDE; - case ViewFrustum::INTERSECT: - intersection = ViewFrustum::INTERSECT; - break; - default: - // DO NOTHING - break; - } - } - return intersection; } bool DiffTraversal::View::usesViewFrustums() const { @@ -204,6 +121,73 @@ bool DiffTraversal::View::isVerySimilar(const View& view) const { return true; } +float DiffTraversal::View::computePriority(const EntityItemPointer& entity) const { + if (!entity) { + return PrioritizedEntity::DO_NOT_SEND; + } + + if (!usesViewFrustums()) { + return PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; + } + + bool success = false; + auto cube = entity->getQueryAACube(success); + if (!success) { + return PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY; + } + + auto center = cube.calcCenter(); // center of bounding sphere + auto radius = 0.5f * SQRT_THREE * cube.getScale(); // radius of bounding sphere + + auto priority = PrioritizedEntity::DO_NOT_SEND; + + for (const auto& frustum : viewFrustums) { + auto position = center - frustum.getPosition(); // position of bounding sphere in view-frame + float distance = glm::length(position); // distance to center of bounding sphere + + // Check the size of the entity, it's possible that a "too small to see" entity is included in a + // larger octree cell because of its position (for example if it crosses the boundary of a cell it + // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen + // before we consider including it. + float angularSize = frustum.getAngularSize(distance, radius); + if (angularSize > lodScaleFactor * MIN_ENTITY_ANGULAR_DIAMETER && + frustum.intersects(position, distance, radius)) { + + // use the angular size as priority + // we compute the max priority for all frustums + priority = std::max(priority, angularSize); + } + } + + return priority; +} + +bool DiffTraversal::View::shouldTraverseElement(const EntityTreeElement& element) const { + if (!usesViewFrustums()) { + return true; + } + + const auto& cube = element.getAACube(); + + auto center = cube.calcCenter(); // center of bounding sphere + auto radius = 0.5f * SQRT_THREE * cube.getScale(); // radius of bounding sphere + + + return any_of(begin(viewFrustums), end(viewFrustums), [&](const ConicalViewFrustum& frustum) { + auto position = center - frustum.getPosition(); // position of bounding sphere in view-frame + float distance = glm::length(position); // distance to center of bounding sphere + + // Check the size of the entity, it's possible that a "too small to see" entity is included in a + // larger octree cell because of its position (for example if it crosses the boundary of a cell it + // pops to the next higher cell. So we want to check to see that the entity is large enough to be seen + // before we consider including it. + float angularSize = frustum.getAngularSize(distance, radius); + + return angularSize > lodScaleFactor * MIN_ELEMENT_ANGULAR_DIAMETER && + frustum.intersects(position, distance, radius); + }); +} + DiffTraversal::DiffTraversal() { const int32_t MIN_PATH_DEPTH = 16; _path.reserve(MIN_PATH_DEPTH); @@ -262,7 +246,6 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View void DiffTraversal::getNextVisibleElement(DiffTraversal::VisibleElement& next) { if (_path.empty()) { next.element.reset(); - next.intersection = ViewFrustum::OUTSIDE; return; } _getNextVisibleElementCallback(next); diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index 0fd014ac23..d62c7b8ee1 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -12,7 +12,7 @@ #ifndef hifi_DiffTraversal_h #define hifi_DiffTraversal_h -#include +#include #include "EntityTreeElement.h" @@ -24,19 +24,18 @@ public: class VisibleElement { public: EntityTreeElementPointer element; - ViewFrustum::intersection intersection { ViewFrustum::OUTSIDE }; }; // View is a struct with a ViewFrustum and LOD parameters class View { public: - bool isBigEnough(const AACube& cube, float minDiameter = MIN_ENTITY_ANGULAR_DIAMETER) const; - bool intersects(const AACube& cube) const; bool usesViewFrustums() const; bool isVerySimilar(const View& view) const; - ViewFrustum::intersection calculateIntersection(const AACube& cube) const; - ViewFrustums viewFrustums; + bool shouldTraverseElement(const EntityTreeElement& element) const; + float computePriority(const EntityItemPointer& entity) const; + + ConicalViewFrustums viewFrustums; uint64_t startTime { 0 }; float lodScaleFactor { 1.0f }; }; @@ -65,9 +64,6 @@ public: Type prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root); const View& getCurrentView() const { return _currentView; } - const View& getCompletedView() const { return _completedView; } - - bool doesCurrentUseViewFrustum() const { return _currentView.usesViewFrustums(); } uint64_t getStartOfCompletedTraversal() const { return _completedView.startTime; } bool finished() const { return _path.empty(); } diff --git a/assignment-client/src/entities/EntityPriorityQueue.h b/libraries/entities/src/EntityPriorityQueue.h similarity index 70% rename from assignment-client/src/entities/EntityPriorityQueue.h rename to libraries/entities/src/EntityPriorityQueue.h index 9210ac549f..354cd70af3 100644 --- a/assignment-client/src/entities/EntityPriorityQueue.h +++ b/libraries/entities/src/EntityPriorityQueue.h @@ -15,44 +15,14 @@ #include #include -#include -#include -#include - -const float SQRT_TWO_OVER_TWO = 0.7071067811865f; -const float DEFAULT_VIEW_RADIUS = 10.0f; - -// ConicalViewFrustum is an approximation of a ViewFrustum for fast calculation of sort priority. -class ConicalViewFrustum { -public: - ConicalViewFrustum() {} - ConicalViewFrustum(const ViewFrustum& viewFrustum) { set(viewFrustum); } - void set(const ViewFrustum& viewFrustum); - float computePriority(const AACube& cube) const; -private: - glm::vec3 _position { 0.0f, 0.0f, 0.0f }; - glm::vec3 _direction { 0.0f, 0.0f, 1.0f }; - float _sinAngle { SQRT_TWO_OVER_TWO }; - float _cosAngle { SQRT_TWO_OVER_TWO }; - float _radius { DEFAULT_VIEW_RADIUS }; -}; - -// Simple wrapper around a set of conical view frustums -class ConicalView { -public: - ConicalView() {} - void set(const DiffTraversal::View& view); - float computePriority(const AACube& cube) const; -private: - std::vector _conicalViewFrustums; -}; +#include "EntityItem.h" // PrioritizedEntity is a placeholder in a sorted queue. class PrioritizedEntity { public: - static const float DO_NOT_SEND; - static const float FORCE_REMOVE; - static const float WHEN_IN_DOUBT_PRIORITY; + static constexpr float DO_NOT_SEND { -1.0e-6f }; + static constexpr float FORCE_REMOVE { -1.0e-5f }; + static constexpr float WHEN_IN_DOUBT_PRIORITY { 1.0f }; PrioritizedEntity(EntityItemPointer entity, float priority, bool forceRemove = false) : _weakEntity(entity), _rawEntityPointer(entity.get()), _priority(priority), _forceRemove(forceRemove) {} EntityItemPointer getEntity() const { return _weakEntity.lock(); } diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 72710a6a7d..1776d63173 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -222,6 +222,12 @@ int unpackOrientationQuatFromSixBytes(const unsigned char* buffer, glm::quat& qu return 6; } +bool closeEnough(float a, float b, float relativeError) { + assert(relativeError >= 0.0f); + // NOTE: we add EPSILON to the denominator so we can avoid checking for division by zero. + // This method works fine when: fabsf(a + b) >> EPSILON + return fabsf(a - b) / (0.5f * fabsf(a + b) + EPSILON) < relativeError; +} // Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's // http://www.geometrictools.com/Documentation/EulerAngles.pdf (via Clyde, diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 5c9a8b5ca1..0e1af27cd2 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -137,6 +137,8 @@ int unpackFloatScalarFromSignedTwoByteFixed(const int16_t* byteFixedPointer, flo int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix); int unpackFloatVec3FromSignedTwoByteFixed(const unsigned char* sourceBuffer, glm::vec3& destination, int radix); +bool closeEnough(float a, float b, float relativeError); + /// \return vec3 with euler angles in radians glm::vec3 safeEulerAngles(const glm::quat& q); diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index c2b92aac5f..c89a9fbd60 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -338,13 +338,6 @@ bool ViewFrustum::boxIntersectsKeyhole(const AABox& box) const { return true; } -bool closeEnough(float a, float b, float relativeError) { - assert(relativeError >= 0.0f); - // NOTE: we add EPSILON to the denominator so we can avoid checking for division by zero. - // This method works fine when: fabsf(a + b) >> EPSILON - return fabsf(a - b) / (0.5f * fabsf(a + b) + EPSILON) < relativeError; -} - // TODO: the slop and relative error should be passed in by argument rather than hard-coded. bool ViewFrustum::isVerySimilar(const ViewFrustum& other) const { const float MIN_POSITION_SLOP_SQUARED = 25.0f; // 5 meters squared diff --git a/libraries/shared/src/shared/ConicalViewFrustum.cpp b/libraries/shared/src/shared/ConicalViewFrustum.cpp new file mode 100644 index 0000000000..906bbc48a3 --- /dev/null +++ b/libraries/shared/src/shared/ConicalViewFrustum.cpp @@ -0,0 +1,125 @@ +// +// ConicalViewFrustum.cpp +// libraries/shared/src/shared +// +// Created by Clement Brisset 4/26/18 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ConicalViewFrustum.h" + +#include "../ViewFrustum.h" + +void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) { + // The ConicalViewFrustum has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part. + // Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum. + _position = viewFrustum.getPosition(); + _direction = viewFrustum.getDirection(); + _radius = viewFrustum.getCenterRadius(); + _farClip = viewFrustum.getFarClip(); + + // Considering the rectangle intersection the frustum and the perpendicular plane 1 unit + // away from the frustum's origin + // We are looking for the angle between the ray that goes through the center of the rectangle + // and the ray that goes through one of the corners of the rectangle + // (Both rays coming from the frustum's origin) + // This angle will let us construct a cone in which the frustum is inscribed + // Let's define: + // A = aspect ratio = width / height + // fov = vertical field of view + // y = half height of the rectangle + // x = half width of the rectangle + // r = half diagonal of the rectangle + // then, we have: + // y / 1 = tan(fov / 2) + // x = A * y = A * tan(fov / 2) + // r^2 = x^2 + y^2 = (A^2 + 1) * tan^2(fov / 2) + // r / 1 = tan(angle) = sqrt((A^2 + 1) * tan^2(fov / 2)) + // angle = atan(sqrt((A^2 + 1) * tan^2(fov / 2))) + float A = viewFrustum.getAspectRatio(); + float t = tanf(0.5f * viewFrustum.getFieldOfView()); + + auto tan2Angle = (A * A + 1.0f) * (t * t); + _angle = atanf(sqrt(tan2Angle)); + + calculate(); +} + +void ConicalViewFrustum::calculate() { + _cosAngle = cosf(_angle); + _sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle); +} + +bool ConicalViewFrustum::isVerySimilar(const ConicalViewFrustum& other) const { + const float MIN_POSITION_SLOP_SQUARED = 25.0f; // 5 meters squared + const float MIN_ANGLE_BETWEEN = 0.174533f; // radian angle between 2 vectors 10 degrees apart + const float MIN_RELATIVE_ERROR = 0.01f; // 1% + + return glm::distance2(_position, other._position) < MIN_POSITION_SLOP_SQUARED && + angleBetween(_direction, other._direction) > MIN_ANGLE_BETWEEN && + closeEnough(_angle, other._angle, MIN_RELATIVE_ERROR) && + closeEnough(_farClip, other._farClip, MIN_RELATIVE_ERROR) && + closeEnough(_radius, other._radius, MIN_RELATIVE_ERROR); +} + +bool ConicalViewFrustum::intersects(const glm::vec3& position, float distance, float radius) const { + if (distance < _radius + radius) { + // Inside keyhole radius + return true; + } + if (distance > _farClip + radius) { + // Past far clip + return false; + } + + // We check the angle between the center of the cube and the _direction of the view. + // If it is less than the sum of the half-angle from center of cone to outer edge plus + // the half apparent angle of the bounding sphere then it is in view. + // + // The math here is left as an exercise for the reader with the following hints: + // (1) We actually check the dot product of the cube's local position rather than the angle and + // (2) we take advantage of this trig identity: cos(A+B) = cos(A)*cos(B) - sin(A)*sin(B) + return glm::dot(position, _direction) > + sqrtf(distance * distance - radius * radius) * _cosAngle - radius * _sinAngle; +} + +bool ConicalViewFrustum::getAngularSize(float distance, float radius) const { + const float AVOID_DIVIDE_BY_ZERO = 0.001f; + float angularSize = radius / (distance + AVOID_DIVIDE_BY_ZERO); + return angularSize; +} + +int ConicalViewFrustum::serialize(unsigned char* destinationBuffer) const { + const unsigned char* startPosition = destinationBuffer; + + memcpy(destinationBuffer, &_position, sizeof(_position)); + destinationBuffer += sizeof(_position); + memcpy(destinationBuffer, &_direction, sizeof(_direction)); + destinationBuffer += sizeof(_direction); + destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _angle); + destinationBuffer += packClipValueToTwoByte(destinationBuffer, _farClip); + memcpy(destinationBuffer, &_radius, sizeof(_radius)); + destinationBuffer += sizeof(_radius); + + return destinationBuffer - startPosition; +} + +int ConicalViewFrustum::deserialize(const unsigned char* sourceBuffer) { + const unsigned char* startPosition = sourceBuffer; + + memcpy(&_position, sourceBuffer, sizeof(_position)); + sourceBuffer += sizeof(_position); + memcpy(&_direction, sourceBuffer, sizeof(_direction)); + sourceBuffer += sizeof(_direction); + sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*)sourceBuffer, &_angle); + sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer, _farClip); + memcpy(&_radius, sourceBuffer, sizeof(_radius)); + sourceBuffer += sizeof(_radius); + + calculate(); + + return sourceBuffer - startPosition; +} diff --git a/libraries/shared/src/shared/ConicalViewFrustum.h b/libraries/shared/src/shared/ConicalViewFrustum.h new file mode 100644 index 0000000000..3cadedda9d --- /dev/null +++ b/libraries/shared/src/shared/ConicalViewFrustum.h @@ -0,0 +1,64 @@ +// +// ConicalViewFrustum.h +// libraries/shared/src/shared +// +// Created by Clement Brisset 4/26/18 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ConicalViewFrustum_h +#define hifi_ConicalViewFrustum_h + +#include + +#include + +class AACube; +class ViewFrustum; +using ViewFrustums = std::vector; + +const float SQRT_TWO_OVER_TWO = 0.7071067811865f; +const float DEFAULT_VIEW_ANGLE = 1.0f; +const float DEFAULT_VIEW_RADIUS = 10.0f; +const float DEFAULT_VIEW_FAR_CLIP = 100.0f; + +// ConicalViewFrustum is an approximation of a ViewFrustum for fast calculation of sort priority. +class ConicalViewFrustum { +public: + ConicalViewFrustum() = default; + ConicalViewFrustum(const ViewFrustum& viewFrustum) { set(viewFrustum); } + + void set(const ViewFrustum& viewFrustum); + void calculate(); + + const glm::vec3& getPosition() const { return _position; } + const glm::vec3& getDirection() const { return _direction; } + float getAngle() const { return _angle; } + float getRadius() const { return _radius; } + float getFarClip() const { return _farClip; } + + bool isVerySimilar(const ConicalViewFrustum& other) const; + + bool intersects(const glm::vec3& position, float distance, float radius) const; + bool getAngularSize(float distance, float radius) const; + + int serialize(unsigned char* destinationBuffer) const; + int deserialize(const unsigned char* sourceBuffer); + +private: + glm::vec3 _position { 0.0f, 0.0f, 0.0f }; + glm::vec3 _direction { 0.0f, 0.0f, 1.0f }; + float _angle { DEFAULT_VIEW_ANGLE }; + float _radius { DEFAULT_VIEW_RADIUS }; + float _farClip { DEFAULT_VIEW_FAR_CLIP }; + + float _sinAngle { SQRT_TWO_OVER_TWO }; + float _cosAngle { SQRT_TWO_OVER_TWO }; +}; +using ConicalViewFrustums = std::vector; + + +#endif /* hifi_ConicalViewFrustum_h */ From e400eb4ed2c86f6132896404849b70193c63c4ae Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 30 Apr 2018 19:50:00 -0700 Subject: [PATCH 131/174] Rename ViewFrustum packets to AvatarQuery --- assignment-client/src/Agent.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 6 +++--- assignment-client/src/avatars/AvatarMixer.h | 2 +- interface/src/Application.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.cpp | 6 +++--- libraries/networking/src/udt/PacketHeaders.h | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 0b373e511b..0183248648 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -618,7 +618,7 @@ void Agent::sendAvatarViewFrustum() { uint8_t numFrustums = 1; auto viewFrustumByteArray = view.toByteArray(); - auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size() + sizeof(numFrustums)); + auto avatarPacket = NLPacket::create(PacketType::AvatarQuery, viewFrustumByteArray.size() + sizeof(numFrustums)); avatarPacket->writePrimitive(numFrustums); avatarPacket->write(viewFrustumByteArray); diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 6353a1664f..d74c76032d 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -47,7 +47,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) : auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListener(PacketType::AvatarData, this, "queueIncomingPacket"); packetReceiver.registerListener(PacketType::AdjustAvatarSorting, this, "handleAdjustAvatarSorting"); - packetReceiver.registerListener(PacketType::ViewFrustum, this, "handleViewFrustumPacket"); + packetReceiver.registerListener(PacketType::AvatarQuery, this, "handleAvatarQueryPacket"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket"); @@ -517,7 +517,7 @@ void AvatarMixer::handleAdjustAvatarSorting(QSharedPointer mess } -void AvatarMixer::handleViewFrustumPacket(QSharedPointer message, SharedNodePointer senderNode) { +void AvatarMixer::handleAvatarQueryPacket(QSharedPointer message, SharedNodePointer senderNode) { auto start = usecTimestampNow(); getOrCreateClientData(senderNode); @@ -683,7 +683,7 @@ void AvatarMixer::sendStatsPacket() { incomingPacketStats["handleNodeIgnoreRequestPacket"] = TIGHT_LOOP_STAT_UINT64(_handleNodeIgnoreRequestPacketElapsedTime); incomingPacketStats["handleRadiusIgnoreRequestPacket"] = TIGHT_LOOP_STAT_UINT64(_handleRadiusIgnoreRequestPacketElapsedTime); incomingPacketStats["handleRequestsDomainListDataPacket"] = TIGHT_LOOP_STAT_UINT64(_handleRequestsDomainListDataPacketElapsedTime); - incomingPacketStats["handleViewFrustumPacket"] = TIGHT_LOOP_STAT_UINT64(_handleViewFrustumPacketElapsedTime); + incomingPacketStats["handleAvatarQueryPacket"] = TIGHT_LOOP_STAT_UINT64(_handleViewFrustumPacketElapsedTime); singleCoreTasks["incoming_packets"] = incomingPacketStats; singleCoreTasks["sendStats"] = (float)_sendStatsElapsedTime; diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 1fbfd7338b..9ef5903eec 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -46,7 +46,7 @@ public slots: private slots: void queueIncomingPacket(QSharedPointer message, SharedNodePointer node); void handleAdjustAvatarSorting(QSharedPointer message, SharedNodePointer senderNode); - void handleViewFrustumPacket(QSharedPointer message, SharedNodePointer senderNode); + void handleAvatarQueryPacket(QSharedPointer message, SharedNodePointer senderNode); void handleAvatarIdentityPacket(QSharedPointer message, SharedNodePointer senderNode); void handleKillAvatarPacket(QSharedPointer message, SharedNodePointer senderNode); void handleNodeIgnoreRequestPacket(QSharedPointer message, SharedNodePointer senderNode); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5e10d29505..a1301ff43e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5852,7 +5852,7 @@ void Application::sendAvatarViewFrustum() { viewFrustumByteArray += _secondaryViewFrustum.toByteArray(); } - auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size() + sizeof(numFrustums)); + auto avatarPacket = NLPacket::create(PacketType::AvatarQuery, viewFrustumByteArray.size() + sizeof(numFrustums)); avatarPacket->writePrimitive(numFrustums); avatarPacket->write(viewFrustumByteArray); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 17b0d90cfe..123e11b7c5 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -34,7 +34,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityPhysics: return static_cast(EntityVersion::MaterialData); case PacketType::EntityQuery: - return static_cast(EntityQueryPacketVersion::MultiFrustumQuery); + return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: case PacketType::AvatarData: case PacketType::BulkAvatarData: @@ -90,8 +90,8 @@ PacketVersion versionForPacketType(PacketType packetType) { return 18; // replace min_avatar_scale and max_avatar_scale with min_avatar_height and max_avatar_height case PacketType::Ping: return static_cast(PingVersion::IncludeConnectionID); - case PacketType::ViewFrustum: - return static_cast(ViewFrustumVersion::SendMultipleFrustums); + case PacketType::AvatarQuery: + return static_cast(AvatarQueryVersion::SendMultipleFrustums); default: return 20; } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index c72bbb0129..20fe23a19a 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -103,7 +103,7 @@ public: RadiusIgnoreRequest, UsernameFromIDRequest, UsernameFromIDReply, - ViewFrustum, + AvatarQuery, RequestsDomainListData, PerAvatarGainSet, EntityScriptGetStatus, @@ -328,7 +328,7 @@ enum class PingVersion : PacketVersion { IncludeConnectionID = 18 }; -enum class ViewFrustumVersion : PacketVersion { +enum class AvatarQueryVersion : PacketVersion { SendMultipleFrustums = 21 }; From 67c119cd2ef39c44e970bb9cedbb2e76a41bdfc5 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 30 Apr 2018 19:50:51 -0700 Subject: [PATCH 132/174] Send Entity Query via conical frustums --- .../src/entities/EntityTreeSendThread.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- libraries/octree/src/OctreeQuery.cpp | 16 ++++------------ libraries/octree/src/OctreeQuery.h | 9 +++------ libraries/octree/src/OctreeQueryNode.cpp | 4 ++-- libraries/octree/src/OctreeQueryNode.h | 12 ++++++------ 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 0d943055f4..1851714f0d 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -108,7 +108,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O DiffTraversal::View newView; - ViewFrustum viewFrustum; + ConicalViewFrustum viewFrustum; if (nodeData->hasMainViewFrustum()) { nodeData->copyCurrentMainViewFrustum(viewFrustum); newView.viewFrustums.push_back(viewFrustum); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 20fe23a19a..1bedfdf3e6 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -245,7 +245,8 @@ enum class EntityQueryPacketVersion: PacketVersion { JSONFilterWithFamilyTree = 19, ConnectionIdentifier = 20, RemovedJurisdictions = 21, - MultiFrustumQuery = 22 + MultiFrustumQuery = 22, + ConicalFrustums = 23 }; enum class AssetServerPacketVersion: PacketVersion { diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 18e907cb8c..6b3f7b8e05 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -50,15 +50,11 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += sizeof(frustumFlags); if (_hasMainFrustum) { - auto byteArray = _mainViewFrustum.toByteArray(); - memcpy(destinationBuffer, byteArray.constData(), byteArray.size()); - destinationBuffer += byteArray.size(); + destinationBuffer += _mainViewFrustum.serialize(destinationBuffer); } if (_hasSecondaryFrustum) { - auto byteArray = _secondaryViewFrustum.toByteArray(); - memcpy(destinationBuffer, byteArray.constData(), byteArray.size()); - destinationBuffer += byteArray.size(); + destinationBuffer += _secondaryViewFrustum.serialize(destinationBuffer); } // desired Max Octree PPS @@ -131,15 +127,11 @@ int OctreeQuery::parseData(ReceivedMessage& message) { _hasSecondaryFrustum = frustumFlags & QUERY_HAS_SECONDARY_FRUSTUM; if (_hasMainFrustum) { - auto bytesLeft = endPosition - sourceBuffer; - auto byteArray = QByteArray::fromRawData(reinterpret_cast(sourceBuffer), bytesLeft); - sourceBuffer += _mainViewFrustum.fromByteArray(byteArray); + sourceBuffer += _mainViewFrustum.deserialize(sourceBuffer); } if (_hasSecondaryFrustum) { - auto bytesLeft = endPosition - sourceBuffer; - auto byteArray = QByteArray::fromRawData(reinterpret_cast(sourceBuffer), bytesLeft); - sourceBuffer += _secondaryViewFrustum.fromByteArray(byteArray); + sourceBuffer += _secondaryViewFrustum.deserialize(sourceBuffer); } // desired Max Octree PPS diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index ef52e29f51..f28d4c317e 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -16,8 +16,7 @@ #include #include - -#include +#include #include "OctreeConstants.h" @@ -37,12 +36,10 @@ public: bool hasMainViewFrustum() const { return _hasMainFrustum; } void setMainViewFrustum(const ViewFrustum& viewFrustum) { _hasMainFrustum = true; _mainViewFrustum = viewFrustum; } void clearMainViewFrustum() { _hasMainFrustum = false; } - const ViewFrustum& getMainViewFrustum() const { return _mainViewFrustum; } bool hasSecondaryViewFrustum() const { return _hasSecondaryFrustum; } void setSecondaryViewFrustum(const ViewFrustum& viewFrustum) { _hasSecondaryFrustum = true; _secondaryViewFrustum = viewFrustum; } void clearSecondaryViewFrustum() { _hasSecondaryFrustum = false; } - const ViewFrustum& getSecondaryViewFrustum() const { return _secondaryViewFrustum; } // getters/setters for JSON filter QJsonObject getJSONParameters() { QReadLocker locker { &_jsonParametersLock }; return _jsonParameters; } @@ -68,9 +65,9 @@ public slots: protected: bool _hasMainFrustum { false }; - ViewFrustum _mainViewFrustum; + ConicalViewFrustum _mainViewFrustum; bool _hasSecondaryFrustum { false }; - ViewFrustum _secondaryViewFrustum; + ConicalViewFrustum _secondaryViewFrustum; // octree server sending items int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index d6e9343896..568504a344 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -139,12 +139,12 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by } } -void OctreeQueryNode::copyCurrentMainViewFrustum(ViewFrustum& viewOut) const { +void OctreeQueryNode::copyCurrentMainViewFrustum(ConicalViewFrustum& viewOut) const { QMutexLocker viewLocker(&_viewMutex); viewOut = _currentMainViewFrustum; } -void OctreeQueryNode::copyCurrentSecondaryViewFrustum(ViewFrustum& viewOut) const { +void OctreeQueryNode::copyCurrentSecondaryViewFrustum(ConicalViewFrustum& viewOut) const { QMutexLocker viewLocker(&_viewMutex); viewOut = _currentSecondaryViewFrustum; } diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h index d8f05c4043..13337c2c69 100644 --- a/libraries/octree/src/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -14,14 +14,14 @@ #include -#include +#include + #include "OctreeConstants.h" #include "OctreeElementBag.h" #include "OctreePacketData.h" #include "OctreeQuery.h" #include "OctreeSceneStats.h" #include "SentPacketHistory.h" -#include class OctreeSendThread; class OctreeServer; @@ -49,8 +49,8 @@ public: OctreeElementExtraEncodeData extraEncodeData; - void copyCurrentMainViewFrustum(ViewFrustum& viewOut) const; - void copyCurrentSecondaryViewFrustum(ViewFrustum& viewOut) const; + void copyCurrentMainViewFrustum(ConicalViewFrustum& viewOut) const; + void copyCurrentSecondaryViewFrustum(ConicalViewFrustum& viewOut) const; // These are not classic setters because they are calculating and maintaining state // which is set asynchronously through the network receive @@ -97,8 +97,8 @@ private: quint64 _firstSuppressedPacket { usecTimestampNow() }; mutable QMutex _viewMutex { QMutex::Recursive }; - ViewFrustum _currentMainViewFrustum; - ViewFrustum _currentSecondaryViewFrustum; + ConicalViewFrustum _currentMainViewFrustum; + ConicalViewFrustum _currentSecondaryViewFrustum; bool _viewFrustumChanging { false }; bool _viewFrustumJustStoppedChanging { true }; From b4ea32bbb6fb7884dbbe8dd0450ae98ac0b0cdfa Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 30 Apr 2018 19:51:18 -0700 Subject: [PATCH 133/174] Correctly compute conical frustum for irregular ones --- .../shared/src/shared/ConicalViewFrustum.cpp | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/libraries/shared/src/shared/ConicalViewFrustum.cpp b/libraries/shared/src/shared/ConicalViewFrustum.cpp index 906bbc48a3..c73a722f0e 100644 --- a/libraries/shared/src/shared/ConicalViewFrustum.cpp +++ b/libraries/shared/src/shared/ConicalViewFrustum.cpp @@ -17,38 +17,24 @@ void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) { // The ConicalViewFrustum has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part. // Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum. _position = viewFrustum.getPosition(); - _direction = viewFrustum.getDirection(); _radius = viewFrustum.getCenterRadius(); _farClip = viewFrustum.getFarClip(); - // Considering the rectangle intersection the frustum and the perpendicular plane 1 unit - // away from the frustum's origin - // We are looking for the angle between the ray that goes through the center of the rectangle - // and the ray that goes through one of the corners of the rectangle - // (Both rays coming from the frustum's origin) - // This angle will let us construct a cone in which the frustum is inscribed - // Let's define: - // A = aspect ratio = width / height - // fov = vertical field of view - // y = half height of the rectangle - // x = half width of the rectangle - // r = half diagonal of the rectangle - // then, we have: - // y / 1 = tan(fov / 2) - // x = A * y = A * tan(fov / 2) - // r^2 = x^2 + y^2 = (A^2 + 1) * tan^2(fov / 2) - // r / 1 = tan(angle) = sqrt((A^2 + 1) * tan^2(fov / 2)) - // angle = atan(sqrt((A^2 + 1) * tan^2(fov / 2))) - float A = viewFrustum.getAspectRatio(); - float t = tanf(0.5f * viewFrustum.getFieldOfView()); + auto topLeft = viewFrustum.getNearTopLeft() - _position; + auto topRight = viewFrustum.getNearTopRight() - _position; + auto bottomLeft = viewFrustum.getNearBottomLeft() - _position; + auto bottomRight = viewFrustum.getNearBottomRight() - _position; + auto centerAxis = 0.25f * (topLeft + topRight + bottomLeft + bottomRight); // Take the average - auto tan2Angle = (A * A + 1.0f) * (t * t); - _angle = atanf(sqrt(tan2Angle)); - - calculate(); + _direction = glm::normalize(centerAxis); + _angle = std::max(std::max(angleBetween(_direction, topLeft), + angleBetween(_direction, topRight)), + std::max(angleBetween(_direction, bottomLeft), + angleBetween(_direction, bottomRight))); } void ConicalViewFrustum::calculate() { + // Pre-compute cos and sin for faster checks _cosAngle = cosf(_angle); _sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle); } From 3283c5eaeca6bb13ddd70add0f93e88b91804916 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 12:37:51 -0700 Subject: [PATCH 134/174] Fix inverted comparaison --- libraries/octree/src/OctreeQuery.cpp | 1 - libraries/shared/src/shared/ConicalViewFrustum.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 6b3f7b8e05..7aa702138f 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -95,7 +95,6 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { int OctreeQuery::parseData(ReceivedMessage& message) { const unsigned char* startPosition = reinterpret_cast(message.getRawMessage()); - const unsigned char* endPosition = startPosition + message.getSize(); const unsigned char* sourceBuffer = startPosition; // unpack the connection ID diff --git a/libraries/shared/src/shared/ConicalViewFrustum.cpp b/libraries/shared/src/shared/ConicalViewFrustum.cpp index c73a722f0e..8538543da6 100644 --- a/libraries/shared/src/shared/ConicalViewFrustum.cpp +++ b/libraries/shared/src/shared/ConicalViewFrustum.cpp @@ -45,7 +45,7 @@ bool ConicalViewFrustum::isVerySimilar(const ConicalViewFrustum& other) const { const float MIN_RELATIVE_ERROR = 0.01f; // 1% return glm::distance2(_position, other._position) < MIN_POSITION_SLOP_SQUARED && - angleBetween(_direction, other._direction) > MIN_ANGLE_BETWEEN && + angleBetween(_direction, other._direction) < MIN_ANGLE_BETWEEN && closeEnough(_angle, other._angle, MIN_RELATIVE_ERROR) && closeEnough(_farClip, other._farClip, MIN_RELATIVE_ERROR) && closeEnough(_radius, other._radius, MIN_RELATIVE_ERROR); From 27c471ee9774f2fd98c0584402ad7a7242c5ad18 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 15:57:26 -0700 Subject: [PATCH 135/174] Move all wire frustums to conical frustums --- assignment-client/src/Agent.cpp | 14 +++- .../src/avatars/AvatarMixerClientData.cpp | 15 ++-- .../src/avatars/AvatarMixerClientData.h | 6 +- .../src/entities/EntityTreeSendThread.cpp | 11 +-- .../src/octree/OctreeHeadlessViewer.cpp | 5 +- .../src/octree/OctreeSendThread.cpp | 2 +- interface/src/Application.cpp | 80 ++++++++++--------- interface/src/Application.h | 14 ++-- interface/src/avatar/AvatarManager.cpp | 13 +-- .../src/EntityTreeRenderer.cpp | 19 +---- .../src/EntityTreeRenderer.h | 3 +- libraries/octree/src/OctreeQuery.cpp | 46 ++++------- libraries/octree/src/OctreeQuery.h | 15 +--- libraries/octree/src/OctreeQueryNode.cpp | 29 +++---- libraries/octree/src/OctreeQueryNode.h | 6 +- libraries/octree/src/OctreeUtils.h | 3 +- .../src/AbstractViewStateInterface.h | 6 +- libraries/shared/src/NumericalConstants.h | 2 + libraries/shared/src/PrioritySortUtil.h | 16 ++-- libraries/shared/src/ViewFrustum.cpp | 63 --------------- libraries/shared/src/ViewFrustum.h | 3 - .../shared/src/shared/ConicalViewFrustum.cpp | 47 +++++++++-- .../shared/src/shared/ConicalViewFrustum.h | 8 +- tests/render-perf/src/main.cpp | 12 +-- 24 files changed, 181 insertions(+), 257 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 0183248648..da811b8af5 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -614,13 +614,19 @@ void Agent::sendAvatarViewFrustum() { view.setPosition(scriptedAvatar->getWorldPosition()); view.setOrientation(scriptedAvatar->getHeadOrientation()); view.calculate(); + ConicalViewFrustum conicalView { view }; + + auto avatarPacket = NLPacket::create(PacketType::AvatarQuery); + auto destinationBuffer = reinterpret_cast(avatarPacket->getPayload()); + auto bufferStart = destinationBuffer; uint8_t numFrustums = 1; - auto viewFrustumByteArray = view.toByteArray(); + memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums)); + destinationBuffer += sizeof(numFrustums); - auto avatarPacket = NLPacket::create(PacketType::AvatarQuery, viewFrustumByteArray.size() + sizeof(numFrustums)); - avatarPacket->writePrimitive(numFrustums); - avatarPacket->write(viewFrustumByteArray); + destinationBuffer += conicalView.serialize(destinationBuffer); + + avatarPacket->setPayloadSize(destinationBuffer - bufferStart); DependencyManager::get()->broadcastToNodes(std::move(avatarPacket), { NodeType::AvatarMixer }); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index a8e5a7c541..aa93fc9e08 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -128,15 +128,16 @@ void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, void AvatarMixerClientData::readViewFrustumPacket(QByteArray message) { _currentViewFrustums.clear(); + + auto sourceBuffer = reinterpret_cast(message.constData()); uint8_t numFrustums = 0; - memcpy(&numFrustums, message.constData(), sizeof(numFrustums)); - message.remove(0, sizeof(numFrustums)); + memcpy(&numFrustums, sourceBuffer, sizeof(numFrustums)); + sourceBuffer += sizeof(numFrustums); for (uint8_t i = 0; i < numFrustums; ++i) { - ViewFrustum frustum; - auto bytesRead = frustum.fromByteArray(message); - message.remove(0, bytesRead); + ConicalViewFrustum frustum; + sourceBuffer += frustum.deserialize(sourceBuffer); _currentViewFrustums.push_back(frustum); } @@ -144,8 +145,8 @@ void AvatarMixerClientData::readViewFrustumPacket(QByteArray message) { bool AvatarMixerClientData::otherAvatarInView(const AABox& otherAvatarBox) { return std::any_of(std::begin(_currentViewFrustums), std::end(_currentViewFrustums), - [&](const ViewFrustum& viewFrustum) { - return viewFrustum.boxIntersectsKeyhole(otherAvatarBox); + [&](const ConicalViewFrustum& viewFrustum) { + return viewFrustum.intersects(otherAvatarBox); }); } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index f17404b79f..f3b2b587ee 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps"; const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps"; @@ -110,7 +110,7 @@ public: bool getRequestsDomainListData() { return _requestsDomainListData; } void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; } - const ViewFrustums& getViewFrustums() const { return _currentViewFrustums; } + const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; } uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const; void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time); @@ -150,7 +150,7 @@ private: SimpleMovingAverage _avgOtherAvatarDataRate; std::unordered_set _radiusIgnoredOthers; - ViewFrustums _currentViewFrustums; + ConicalViewFrustums _currentViewFrustums; int _recentOtherAvatarsInView { 0 }; int _recentOtherAvatarsOutOfView { 0 }; diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 1851714f0d..f008ef9925 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -107,16 +107,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O DiffTraversal::View newView; - - ConicalViewFrustum viewFrustum; - if (nodeData->hasMainViewFrustum()) { - nodeData->copyCurrentMainViewFrustum(viewFrustum); - newView.viewFrustums.push_back(viewFrustum); - } - if (nodeData->hasSecondaryViewFrustum()) { - nodeData->copyCurrentSecondaryViewFrustum(viewFrustum); - newView.viewFrustums.push_back(viewFrustum); - } + newView.viewFrustums = nodeData->getCurrentViews(); int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); newView.lodScaleFactor = powf(2.0f, lodLevelOffset); diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.cpp b/assignment-client/src/octree/OctreeHeadlessViewer.cpp index 6d91a134c2..039dbdab78 100644 --- a/assignment-client/src/octree/OctreeHeadlessViewer.cpp +++ b/assignment-client/src/octree/OctreeHeadlessViewer.cpp @@ -19,7 +19,10 @@ void OctreeHeadlessViewer::queryOctree() { PacketType packetType = getMyQueryMessageType(); if (_hasViewFrustum) { - _octreeQuery.setMainViewFrustum(_viewFrustum); + ConicalViewFrustums views { _viewFrustum }; + _octreeQuery.setConicalViews(views); + } else { + _octreeQuery.clearConicalViews(); } auto nodeList = DependencyManager::get(); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 40c052659d..482b20272a 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -330,7 +330,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* } else { // we aren't forcing a full scene, check if something else suggests we should isFullScene = nodeData->haveJSONParametersChanged() || - (nodeData->hasMainViewFrustum() && + (nodeData->hasConicalViews() && (nodeData->getViewFrustumJustStoppedChanging() || nodeData->hasLodChanged())); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a1301ff43e..d14af685f0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5230,10 +5230,10 @@ void Application::updateSecondaryCameraViewFrustum() { assert(camera); if (!camera->isEnabled()) { - _hasSecondaryViewFrustum = false; return; } + ViewFrustum secondaryViewFrustum; if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { auto entityScriptingInterface = DependencyManager::get(); auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); @@ -5258,36 +5258,37 @@ void Application::updateSecondaryCameraViewFrustum() { // set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation glm::quat mirrorCameraOrientation = glm::quat_cast(worldFromMirrorRotation); - _secondaryViewFrustum.setPosition(mirrorCameraPositionWorld); - _secondaryViewFrustum.setOrientation(mirrorCameraOrientation); + secondaryViewFrustum.setPosition(mirrorCameraPositionWorld); + secondaryViewFrustum.setOrientation(mirrorCameraOrientation); // build frustum using mirror space translation of mirrored camera float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); - _secondaryViewFrustum.setProjection(frustum); + secondaryViewFrustum.setProjection(frustum); } else { if (!camera->attachedEntityId.isNull()) { auto entityScriptingInterface = DependencyManager::get(); auto entityProperties = entityScriptingInterface->getEntityProperties(camera->attachedEntityId); - _secondaryViewFrustum.setPosition(entityProperties.getPosition()); - _secondaryViewFrustum.setOrientation(entityProperties.getRotation()); + secondaryViewFrustum.setPosition(entityProperties.getPosition()); + secondaryViewFrustum.setOrientation(entityProperties.getRotation()); } else { - _secondaryViewFrustum.setPosition(camera->position); - _secondaryViewFrustum.setOrientation(camera->orientation); + secondaryViewFrustum.setPosition(camera->position); + secondaryViewFrustum.setOrientation(camera->orientation); } float aspectRatio = (float)camera->textureWidth / (float)camera->textureHeight; - _secondaryViewFrustum.setProjection(camera->vFoV, + secondaryViewFrustum.setProjection(camera->vFoV, aspectRatio, camera->nearClipPlaneDistance, camera->farClipPlaneDistance); } // Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera, // which is not what we want here. - _secondaryViewFrustum.calculate(); - _hasSecondaryViewFrustum = true; + secondaryViewFrustum.calculate(); + + _conicalViews.push_back(secondaryViewFrustum); } static bool domainLoadingInProgress = false; @@ -5644,6 +5645,8 @@ void Application::update(float deltaTime) { QMutexLocker viewLocker(&_viewMutex); _myCamera.loadViewFrustum(_viewFrustum); + _conicalViews.clear(); + _conicalViews.push_back(_viewFrustum); // TODO: Fix this by modeling the way the secondary camera works on how the main camera works // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary // camera should be. @@ -5660,18 +5663,29 @@ void Application::update(float deltaTime) { quint64 sinceLastQuery = now - _lastQueriedTime; const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY; - bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum); - viewIsDifferentEnough |= _hasSecondaryViewFrustum && !_lastQueriedSecondaryViewFrustum.isVerySimilar(_secondaryViewFrustum); + + bool viewIsDifferentEnough = false; + if (_conicalViews.size() == _lastQueriedViews.size()) { + for (size_t i = 0; i < _conicalViews.size(); ++i) { + if (!_conicalViews[i].isVerySimilar(_lastQueriedViews[i])) { + viewIsDifferentEnough = true; + break; + } + } + } else { + viewIsDifferentEnough = true; + } + // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it if (queryIsDue || viewIsDifferentEnough) { - _lastQueriedTime = now; if (DependencyManager::get()->shouldRenderEntities()) { queryOctree(NodeType::EntityServer, PacketType::EntityQuery); } sendAvatarViewFrustum(); - _lastQueriedViewFrustum = _viewFrustum; - _lastQueriedSecondaryViewFrustum = _secondaryViewFrustum; + + _lastQueriedViews = _conicalViews; + _lastQueriedTime = now; } } @@ -5844,17 +5858,19 @@ void Application::update(float deltaTime) { } void Application::sendAvatarViewFrustum() { - uint8_t numFrustums = 1; - QByteArray viewFrustumByteArray = _viewFrustum.toByteArray(); + auto avatarPacket = NLPacket::create(PacketType::AvatarQuery); + auto destinationBuffer = reinterpret_cast(avatarPacket->getPayload()); + unsigned char* bufferStart = destinationBuffer; - if (_hasSecondaryViewFrustum) { - ++numFrustums; - viewFrustumByteArray += _secondaryViewFrustum.toByteArray(); + uint8_t numFrustums = _conicalViews.size(); + memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums)); + destinationBuffer += sizeof(numFrustums); + + for (const auto& view : _conicalViews) { + destinationBuffer += view.serialize(destinationBuffer); } - auto avatarPacket = NLPacket::create(PacketType::AvatarQuery, viewFrustumByteArray.size() + sizeof(numFrustums)); - avatarPacket->writePrimitive(numFrustums); - avatarPacket->write(viewFrustumByteArray); + avatarPacket->setPayloadSize(destinationBuffer - bufferStart); DependencyManager::get()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer); } @@ -5916,16 +5932,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { return; // bail early if settings are not loaded } - ViewFrustum viewFrustum; - copyViewFrustum(viewFrustum); - _octreeQuery.setMainViewFrustum(viewFrustum); - - if (hasSecondaryViewFrustum()) { - copySecondaryViewFrustum(viewFrustum); - _octreeQuery.setSecondaryViewFrustum(viewFrustum); - } else { - _octreeQuery.clearSecondaryViewFrustum(); - } + _octreeQuery.setConicalViews(_conicalViews); auto lodManager = DependencyManager::get(); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); @@ -6010,11 +6017,6 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const { viewOut = _displayViewFrustum; } -void Application::copySecondaryViewFrustum(ViewFrustum& viewOut) const { - QMutexLocker viewLocker(&_viewMutex); - viewOut = _secondaryViewFrustum; -} - void Application::resetSensors(bool andReload) { DependencyManager::get()->reset(); DependencyManager::get()->reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 83e719333d..6d749f9458 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -175,14 +176,14 @@ public: Camera& getCamera() { return _myCamera; } const Camera& getCamera() const { return _myCamera; } // Represents the current view frustum of the avatar. - void copyViewFrustum(ViewFrustum& viewOut) const override; - void copySecondaryViewFrustum(ViewFrustum& viewOut) const override; - bool hasSecondaryViewFrustum() const override { return _hasSecondaryViewFrustum; } + void copyViewFrustum(ViewFrustum& viewOut) const; // Represents the view frustum of the current rendering pass, // which might be different from the viewFrustum, i.e. shadowmap // passes, mirror window passes, etc void copyDisplayViewFrustum(ViewFrustum& viewOut) const; + const ConicalViewFrustums& getConicalViews() const override { return _conicalViews; } + const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } QSharedPointer getEntities() const { return DependencyManager::get(); } QUndoStack* getUndoStack() { return &_undoStack; } @@ -574,11 +575,10 @@ private: mutable QMutex _viewMutex { QMutex::Recursive }; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. - ViewFrustum _lastQueriedViewFrustum; // last view frustum used to query octree servers ViewFrustum _displayViewFrustum; - ViewFrustum _secondaryViewFrustum; - ViewFrustum _lastQueriedSecondaryViewFrustum; // last secondary view frustum used to query octree servers - bool _hasSecondaryViewFrustum; + + ConicalViewFrustums _conicalViews; + ConicalViewFrustums _lastQueriedViews; // last views used to query servers quint64 _lastQueriedTime; OctreeQuery _octreeQuery { true }; // NodeData derived class for querying octee cells from octree servers diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 087e23a933..d24618fada 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "Application.h" #include "AvatarManager.h" @@ -156,17 +157,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { }; - ViewFrustums views; - - ViewFrustum view; - qApp->copyCurrentViewFrustum(view); - views.push_back(view); - - if (qApp->hasSecondaryViewFrustum()) { - qApp->copySecondaryViewFrustum(view); - views.push_back(view); - } - + const auto& views = qApp->getConicalViews(); PrioritySortUtil::PriorityQueue sortedAvatars(views, AvatarData::_avatarSortCoefficientSize, AvatarData::_avatarSortCoefficientCenter, diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 6dd13c7332..600d1c32a8 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -296,8 +296,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } } -void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, const ViewFrustums& views, - render::Transaction& transaction) { +void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction) { PROFILE_RANGE_EX(simulation_physics, "ChangeInScene", 0xffff00ff, (uint64_t)_changedEntities.size()); PerformanceTimer pt("change"); std::unordered_set changedEntities; @@ -358,6 +357,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene // prioritize and sort the renderables uint64_t sortStart = usecTimestampNow(); + + const auto& views = _viewState->getConicalViews(); PrioritySortUtil::PriorityQueue sortedRenderables(views); { PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); @@ -417,19 +418,7 @@ void EntityTreeRenderer::update(bool simulate) { render::Transaction transaction; addPendingEntities(scene, transaction); - ViewFrustums views; - - ViewFrustum view; - _viewState->copyViewFrustum(view); - views.push_back(view); - - if (_viewState->hasSecondaryViewFrustum()) { - _viewState->copySecondaryViewFrustum(view); - views.push_back(view); - } - - - updateChangedEntities(scene, views, transaction); + updateChangedEntities(scene, transaction); scene->enqueueTransaction(transaction); } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 9ed4f9d21d..882ec2fd5b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -148,8 +148,7 @@ protected: private: void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction); - void updateChangedEntities(const render::ScenePointer& scene, const ViewFrustums& views, - render::Transaction& transaction); + void updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction); EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); } render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); } diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 7aa702138f..072774f0f5 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -18,10 +18,6 @@ #include #include -using QueryFlags = uint8_t; -const QueryFlags QUERY_HAS_MAIN_FRUSTUM = 1U << 0; -const QueryFlags QUERY_HAS_SECONDARY_FRUSTUM = 1U << 1; - OctreeQuery::OctreeQuery(bool randomizeConnectionID) { if (randomizeConnectionID) { // randomize our initial octree query connection ID using random_device @@ -38,23 +34,13 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { memcpy(destinationBuffer, &_connectionID, sizeof(_connectionID)); destinationBuffer += sizeof(_connectionID); - // flags for wether the frustums are present - QueryFlags frustumFlags = 0; - if (_hasMainFrustum) { - frustumFlags |= QUERY_HAS_MAIN_FRUSTUM; - } - if (_hasSecondaryFrustum) { - frustumFlags |= QUERY_HAS_SECONDARY_FRUSTUM; - } - memcpy(destinationBuffer, &frustumFlags, sizeof(frustumFlags)); - destinationBuffer += sizeof(frustumFlags); + // Number of frustums + uint8_t numFrustums = _conicalViews.size(); + memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums)); + destinationBuffer += sizeof(numFrustums); - if (_hasMainFrustum) { - destinationBuffer += _mainViewFrustum.serialize(destinationBuffer); - } - - if (_hasSecondaryFrustum) { - destinationBuffer += _secondaryViewFrustum.serialize(destinationBuffer); + for (const auto& view : _conicalViews) { + destinationBuffer += view.serialize(destinationBuffer); } // desired Max Octree PPS @@ -118,19 +104,15 @@ int OctreeQuery::parseData(ReceivedMessage& message) { } // check if this query uses a view frustum - QueryFlags frustumFlags { 0 }; - memcpy(&frustumFlags, sourceBuffer, sizeof(frustumFlags)); - sourceBuffer += sizeof(frustumFlags); + uint8_t numFrustums = 0; + memcpy(&numFrustums, sourceBuffer, sizeof(numFrustums)); + sourceBuffer += sizeof(numFrustums); - _hasMainFrustum = frustumFlags & QUERY_HAS_MAIN_FRUSTUM; - _hasSecondaryFrustum = frustumFlags & QUERY_HAS_SECONDARY_FRUSTUM; - - if (_hasMainFrustum) { - sourceBuffer += _mainViewFrustum.deserialize(sourceBuffer); - } - - if (_hasSecondaryFrustum) { - sourceBuffer += _secondaryViewFrustum.deserialize(sourceBuffer); + _conicalViews.clear(); + for (int i = 0; i < numFrustums; ++i) { + ConicalViewFrustum view; + sourceBuffer += view.deserialize(sourceBuffer); + _conicalViews.push_back(view); } // desired Max Octree PPS diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index f28d4c317e..7dfc1cfaaf 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -33,13 +33,9 @@ public: int getBroadcastData(unsigned char* destinationBuffer); int parseData(ReceivedMessage& message) override; - bool hasMainViewFrustum() const { return _hasMainFrustum; } - void setMainViewFrustum(const ViewFrustum& viewFrustum) { _hasMainFrustum = true; _mainViewFrustum = viewFrustum; } - void clearMainViewFrustum() { _hasMainFrustum = false; } - - bool hasSecondaryViewFrustum() const { return _hasSecondaryFrustum; } - void setSecondaryViewFrustum(const ViewFrustum& viewFrustum) { _hasSecondaryFrustum = true; _secondaryViewFrustum = viewFrustum; } - void clearSecondaryViewFrustum() { _hasSecondaryFrustum = false; } + bool hasConicalViews() const { return !_conicalViews.empty(); } + void setConicalViews(ConicalViewFrustums views) { _conicalViews = views; } + void clearConicalViews() { _conicalViews.clear(); } // getters/setters for JSON filter QJsonObject getJSONParameters() { QReadLocker locker { &_jsonParametersLock }; return _jsonParameters; } @@ -64,10 +60,7 @@ public slots: void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; } protected: - bool _hasMainFrustum { false }; - ConicalViewFrustum _mainViewFrustum; - bool _hasSecondaryFrustum { false }; - ConicalViewFrustum _secondaryViewFrustum; + ConicalViewFrustums _conicalViews; // octree server sending items int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS; diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index 568504a344..2d1d89a11c 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -139,23 +139,13 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by } } -void OctreeQueryNode::copyCurrentMainViewFrustum(ConicalViewFrustum& viewOut) const { - QMutexLocker viewLocker(&_viewMutex); - viewOut = _currentMainViewFrustum; -} - -void OctreeQueryNode::copyCurrentSecondaryViewFrustum(ConicalViewFrustum& viewOut) const { - QMutexLocker viewLocker(&_viewMutex); - viewOut = _currentSecondaryViewFrustum; -} - bool OctreeQueryNode::updateCurrentViewFrustum() { // if shutting down, return immediately if (_isShuttingDown) { return false; } - if (!_hasMainFrustum && !_hasSecondaryFrustum) { + if (!hasConicalViews()) { // this client does not use a view frustum so the view frustum for this query has not changed return false; } @@ -164,12 +154,17 @@ bool OctreeQueryNode::updateCurrentViewFrustum() { { // if there has been a change, then recalculate QMutexLocker viewLocker(&_viewMutex); - if (_hasMainFrustum && !_mainViewFrustum.isVerySimilar(_currentMainViewFrustum)) { - _currentMainViewFrustum = _mainViewFrustum; - currentViewFrustumChanged = true; - } - if (_hasSecondaryFrustum && !_secondaryViewFrustum.isVerySimilar(_currentSecondaryViewFrustum)) { - _currentSecondaryViewFrustum = _secondaryViewFrustum; + + if (_conicalViews.size() == _currentConicalViews.size()) { + for (size_t i = 0; i < _conicalViews.size(); ++i) { + if (!_conicalViews[i].isVerySimilar(_currentConicalViews[i])) { + _currentConicalViews = _conicalViews; + currentViewFrustumChanged = true; + break; + } + } + } else { + _currentConicalViews = _conicalViews; currentViewFrustumChanged = true; } } diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h index 13337c2c69..d984e048c1 100644 --- a/libraries/octree/src/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -49,8 +49,7 @@ public: OctreeElementExtraEncodeData extraEncodeData; - void copyCurrentMainViewFrustum(ConicalViewFrustum& viewOut) const; - void copyCurrentSecondaryViewFrustum(ConicalViewFrustum& viewOut) const; + const ConicalViewFrustums& getCurrentViews() const { return _currentConicalViews; } // These are not classic setters because they are calculating and maintaining state // which is set asynchronously through the network receive @@ -97,8 +96,7 @@ private: quint64 _firstSuppressedPacket { usecTimestampNow() }; mutable QMutex _viewMutex { QMutex::Recursive }; - ConicalViewFrustum _currentMainViewFrustum; - ConicalViewFrustum _currentSecondaryViewFrustum; + ConicalViewFrustums _currentConicalViews; bool _viewFrustumChanging { false }; bool _viewFrustumJustStoppedChanging { true }; diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h index 58ab366d8d..dff56cad64 100644 --- a/libraries/octree/src/OctreeUtils.h +++ b/libraries/octree/src/OctreeUtils.h @@ -12,6 +12,8 @@ #ifndef hifi_OctreeUtils_h #define hifi_OctreeUtils_h +#include + #include "OctreeConstants.h" class AABox; @@ -33,7 +35,6 @@ float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust // MIN_ELEMENT_ANGULAR_DIAMETER = angular diameter of 1x1x1m cube at 400m = sqrt(3) / 400 = 0.0043301 radians ~= 0.25 degrees const float MIN_ELEMENT_ANGULAR_DIAMETER = 0.0043301f; // radians // NOTE: the entity bounding cube is larger than the smallest possible containing octree element by sqrt(3) -const float SQRT_THREE = 1.73205080f; const float MIN_ENTITY_ANGULAR_DIAMETER = MIN_ELEMENT_ANGULAR_DIAMETER * SQRT_THREE; const float MIN_VISIBLE_DISTANCE = 0.0001f; // helps avoid divide-by-zero check diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 9d781b7d18..b90e291da5 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -24,6 +24,8 @@ class Transform; class QThread; class ViewFrustum; class PickRay; +class ConicalViewFrustum; +using ConicalViewFrustums = std::vector; /// Interface provided by Application to other objects that need access to the current view state details class AbstractViewStateInterface { @@ -31,9 +33,7 @@ public: /// copies the current view frustum for rendering the view state virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0; - virtual void copyViewFrustum(ViewFrustum& viewOut) const = 0; - virtual void copySecondaryViewFrustum(ViewFrustum& viewOut) const = 0; - virtual bool hasSecondaryViewFrustum() const = 0; + virtual const ConicalViewFrustums& getConicalViews() const = 0; virtual QThread* getMainThread() = 0; diff --git a/libraries/shared/src/NumericalConstants.h b/libraries/shared/src/NumericalConstants.h index e2d2409d56..4c24a73226 100644 --- a/libraries/shared/src/NumericalConstants.h +++ b/libraries/shared/src/NumericalConstants.h @@ -48,6 +48,8 @@ const int BYTES_PER_KILOBYTE = 1000; const int BYTES_PER_KILOBIT = BYTES_PER_KILOBYTE / BITS_IN_BYTE; const int KILO_PER_MEGA = 1000; +const float SQRT_THREE = 1.73205080f; + #define KB_TO_BYTES_SHIFT 10 #define MB_TO_BYTES_SHIFT 20 #define GB_TO_BYTES_SHIFT 30 diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index ba15222611..34ec074d45 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -15,7 +15,7 @@ #include #include "NumericalConstants.h" -#include "ViewFrustum.h" +#include "shared/ConicalViewFrustum.h" /* PrioritySortUtil is a helper for sorting 3D things relative to a ViewFrustum. To use: @@ -84,12 +84,12 @@ namespace PrioritySortUtil { class PriorityQueue { public: PriorityQueue() = delete; - PriorityQueue(const ViewFrustums& views) : _views(views) { } - PriorityQueue(const ViewFrustums& views, float angularWeight, float centerWeight, float ageWeight) + PriorityQueue(const ConicalViewFrustums& views) : _views(views) { } + PriorityQueue(const ConicalViewFrustums& views, float angularWeight, float centerWeight, float ageWeight) : _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight) { } - void setViews(const ViewFrustums& views) { _views = views; } + void setViews(const ConicalViewFrustums& views) { _views = views; } void setWeights(float angularWeight, float centerWeight, float ageWeight) { _angularWeight = angularWeight; @@ -118,7 +118,7 @@ namespace PrioritySortUtil { return priority; } - float computePriority(const ViewFrustum& view, const T& thing) const { + float computePriority(const ConicalViewFrustum& view, const T& thing) const { // priority = weighted linear combination of multiple values: // (a) angular size // (b) proximity to center of view @@ -143,8 +143,8 @@ namespace PrioritySortUtil { + _ageWeight * cosineAngleFactor * age; // decrement priority of things outside keyhole - if (distance - radius > view.getCenterRadius()) { - if (!view.sphereIntersectsFrustum(position, radius)) { + if (distance - radius > view.getRadius()) { + if (!view.intersects(offset, distance, radius)) { constexpr float OUT_OF_VIEW_PENALTY = -10.0f; priority += OUT_OF_VIEW_PENALTY; } @@ -152,7 +152,7 @@ namespace PrioritySortUtil { return priority; } - ViewFrustums _views; + ConicalViewFrustums _views; std::priority_queue _queue; float _angularWeight { DEFAULT_ANGULAR_COEF }; float _centerWeight { DEFAULT_CENTER_COEF }; diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index c89a9fbd60..3aa70b0897 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -138,69 +138,6 @@ const char* ViewFrustum::debugPlaneName (int plane) const { return "Unknown"; } -int ViewFrustum::fromByteArray(const QByteArray& input) { - - // From the wire! - glm::vec3 cameraPosition; - glm::quat cameraOrientation; - float cameraCenterRadius; - float cameraFov; - float cameraAspectRatio; - float cameraNearClip; - float cameraFarClip; - - const unsigned char* startPosition = reinterpret_cast(input.constData()); - const unsigned char* sourceBuffer = startPosition; - - // camera details - memcpy(&cameraPosition, sourceBuffer, sizeof(cameraPosition)); - sourceBuffer += sizeof(cameraPosition); - sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, cameraOrientation); - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*)sourceBuffer, &cameraFov); - sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, cameraAspectRatio); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer, cameraNearClip); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer, cameraFarClip); - memcpy(&cameraCenterRadius, sourceBuffer, sizeof(cameraCenterRadius)); - sourceBuffer += sizeof(cameraCenterRadius); - - setPosition(cameraPosition); - setOrientation(cameraOrientation); - setCenterRadius(cameraCenterRadius); - - // Also make sure it's got the correct lens details from the camera - if (0.0f != cameraAspectRatio && - 0.0f != cameraNearClip && - 0.0f != cameraFarClip && - cameraNearClip != cameraFarClip) { - - setProjection(cameraFov, cameraAspectRatio, cameraNearClip, cameraFarClip); - calculate(); - } - - return sourceBuffer - startPosition; -} - - -QByteArray ViewFrustum::toByteArray() { - static const int LARGE_ENOUGH = 1024; - QByteArray viewFrustumDataByteArray(LARGE_ENOUGH, 0); - unsigned char* destinationBuffer = reinterpret_cast(viewFrustumDataByteArray.data()); - unsigned char* startPosition = destinationBuffer; - - // camera details - memcpy(destinationBuffer, &_position, sizeof(_position)); - destinationBuffer += sizeof(_position); - destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _orientation); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _fieldOfView); - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _aspectRatio); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _nearClip); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _farClip); - memcpy(destinationBuffer, &_centerSphereRadius, sizeof(_centerSphereRadius)); - destinationBuffer += sizeof(_centerSphereRadius); - - return viewFrustumDataByteArray.left(destinationBuffer - startPosition); -} - ViewFrustum::intersection ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const { // only check against frustum ViewFrustum::intersection result = INSIDE; diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 128a717df8..eada65468d 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -147,9 +147,6 @@ public: void invalidate(); // causes all reasonable intersection tests to fail - QByteArray toByteArray(); - int fromByteArray(const QByteArray& input); - private: glm::mat4 _view; glm::mat4 _projection; diff --git a/libraries/shared/src/shared/ConicalViewFrustum.cpp b/libraries/shared/src/shared/ConicalViewFrustum.cpp index 8538543da6..2ef096e3a8 100644 --- a/libraries/shared/src/shared/ConicalViewFrustum.cpp +++ b/libraries/shared/src/shared/ConicalViewFrustum.cpp @@ -11,6 +11,8 @@ #include "ConicalViewFrustum.h" + +#include "../NumericalConstants.h" #include "../ViewFrustum.h" void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) { @@ -45,13 +47,46 @@ bool ConicalViewFrustum::isVerySimilar(const ConicalViewFrustum& other) const { const float MIN_RELATIVE_ERROR = 0.01f; // 1% return glm::distance2(_position, other._position) < MIN_POSITION_SLOP_SQUARED && - angleBetween(_direction, other._direction) < MIN_ANGLE_BETWEEN && - closeEnough(_angle, other._angle, MIN_RELATIVE_ERROR) && - closeEnough(_farClip, other._farClip, MIN_RELATIVE_ERROR) && - closeEnough(_radius, other._radius, MIN_RELATIVE_ERROR); + angleBetween(_direction, other._direction) < MIN_ANGLE_BETWEEN && + closeEnough(_angle, other._angle, MIN_RELATIVE_ERROR) && + closeEnough(_farClip, other._farClip, MIN_RELATIVE_ERROR) && + closeEnough(_radius, other._radius, MIN_RELATIVE_ERROR); } -bool ConicalViewFrustum::intersects(const glm::vec3& position, float distance, float radius) const { +bool ConicalViewFrustum::intersects(const AACube& cube) const { + auto radius = 0.5f * SQRT_THREE * cube.getScale(); // radius of bounding sphere + auto position = cube.calcCenter() - _position; // position of bounding sphere in view-frame + float distance = glm::length(position); + + return intersects(position, distance, radius); +} + +bool ConicalViewFrustum::intersects(const AABox& box) const { + auto radius = 0.5f * glm::length(box.getScale()); // radius of bounding sphere + auto position = box.calcCenter() - _position; // position of bounding sphere in view-frame + float distance = glm::length(position); + + return intersects(position, distance, radius); +} + +bool ConicalViewFrustum::getAngularSize(const AACube& cube) const { + auto radius = 0.5f * SQRT_THREE * cube.getScale(); // radius of bounding sphere + auto position = cube.calcCenter() - _position; // position of bounding sphere in view-frame + float distance = glm::length(position); + + return getAngularSize(distance, radius); +} + +bool ConicalViewFrustum::getAngularSize(const AABox& box) const { + auto radius = 0.5f * glm::length(box.getScale()); // radius of bounding sphere + auto position = box.calcCenter() - _position; // position of bounding sphere in view-frame + float distance = glm::length(position); + + return getAngularSize(distance, radius); +} + + +bool ConicalViewFrustum::intersects(const glm::vec3& relativePosition, float distance, float radius) const { if (distance < _radius + radius) { // Inside keyhole radius return true; @@ -68,7 +103,7 @@ bool ConicalViewFrustum::intersects(const glm::vec3& position, float distance, f // The math here is left as an exercise for the reader with the following hints: // (1) We actually check the dot product of the cube's local position rather than the angle and // (2) we take advantage of this trig identity: cos(A+B) = cos(A)*cos(B) - sin(A)*sin(B) - return glm::dot(position, _direction) > + return glm::dot(relativePosition, _direction) > sqrtf(distance * distance - radius * radius) * _cosAngle - radius * _sinAngle; } diff --git a/libraries/shared/src/shared/ConicalViewFrustum.h b/libraries/shared/src/shared/ConicalViewFrustum.h index 3cadedda9d..dc372d560e 100644 --- a/libraries/shared/src/shared/ConicalViewFrustum.h +++ b/libraries/shared/src/shared/ConicalViewFrustum.h @@ -17,6 +17,7 @@ #include class AACube; +class AABox; class ViewFrustum; using ViewFrustums = std::vector; @@ -42,7 +43,12 @@ public: bool isVerySimilar(const ConicalViewFrustum& other) const; - bool intersects(const glm::vec3& position, float distance, float radius) const; + bool intersects(const AACube& cube) const; + bool intersects(const AABox& box) const; + bool getAngularSize(const AACube& cube) const; + bool getAngularSize(const AABox& box) const; + + bool intersects(const glm::vec3& relativePosition, float distance, float radius) const; bool getAngularSize(float distance, float radius) const; int serialize(unsigned char* destinationBuffer) const; diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 8c17d7c5c2..2e72d9cead 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -441,14 +442,9 @@ protected: viewOut = _viewFrustum; } - void copyViewFrustum(ViewFrustum& viewOut) const override { - viewOut = _viewFrustum; - } - - void copySecondaryViewFrustum(ViewFrustum& viewOut) const override {} - - bool hasSecondaryViewFrustum() const override { - return false; + const ConicalViewFrustums& getConicalViews() const override { + assert(false); + return ConicalViewFrustums(); } QThread* getMainThread() override { From d7e9fdc6a42b0c2940399a6103d80e5d52f5d1e6 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 18:19:25 -0700 Subject: [PATCH 136/174] Bump Avatar Query packet version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 123e11b7c5..d6ab7d0f9c 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -91,7 +91,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::Ping: return static_cast(PingVersion::IncludeConnectionID); case PacketType::AvatarQuery: - return static_cast(AvatarQueryVersion::SendMultipleFrustums); + return static_cast(AvatarQueryVersion::ConicalFrustums); default: return 20; } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 1bedfdf3e6..2252b09ae5 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -330,7 +330,8 @@ enum class PingVersion : PacketVersion { }; enum class AvatarQueryVersion : PacketVersion { - SendMultipleFrustums = 21 + SendMultipleFrustums = 21, + ConicalFrustums = 22 }; #endif // hifi_PacketHeaders_h From d87cd2af6e979f3010bb21a6ac4992a921233238 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 18:23:00 -0700 Subject: [PATCH 137/174] Update avatar query names --- assignment-client/src/Agent.cpp | 14 +++++++------- assignment-client/src/Agent.h | 4 ++-- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index da811b8af5..42924a8487 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -548,18 +548,18 @@ void Agent::setIsAvatar(bool isAvatar) { if (_isAvatar && !_avatarIdentityTimer) { // set up the avatar timers _avatarIdentityTimer = new QTimer(this); - _avatarViewTimer = new QTimer(this); + _avatarQueryTimer = new QTimer(this); // connect our slot connect(_avatarIdentityTimer, &QTimer::timeout, this, &Agent::sendAvatarIdentityPacket); - connect(_avatarViewTimer, &QTimer::timeout, this, &Agent::sendAvatarViewFrustum); + connect(_avatarQueryTimer, &QTimer::timeout, this, &Agent::queryAvatars); static const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; static const int AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS = 1000; // start the timers _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); // FIXME - we shouldn't really need to constantly send identity packets - _avatarViewTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS); + _avatarQueryTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS); // tell the avatarAudioTimer to start ticking QMetaObject::invokeMethod(&_avatarAudioTimer, "start"); @@ -572,9 +572,9 @@ void Agent::setIsAvatar(bool isAvatar) { delete _avatarIdentityTimer; _avatarIdentityTimer = nullptr; - _avatarViewTimer->stop(); - delete _avatarViewTimer; - _avatarViewTimer = nullptr; + _avatarQueryTimer->stop(); + delete _avatarQueryTimer; + _avatarQueryTimer = nullptr; // The avatar mixer never times out a connection (e.g., based on identity or data packets) // but rather keeps avatars in its list as long as "connected". As a result, clients timeout @@ -607,7 +607,7 @@ void Agent::sendAvatarIdentityPacket() { } } -void Agent::sendAvatarViewFrustum() { +void Agent::queryAvatars() { auto scriptedAvatar = DependencyManager::get(); ViewFrustum view; diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index d144f0bc01..0cdc9e0029 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -97,7 +97,7 @@ private: void setAvatarSound(SharedSoundPointer avatarSound) { _avatarSound = avatarSound; } void sendAvatarIdentityPacket(); - void sendAvatarViewFrustum(); + void queryAvatars(); QString _scriptContents; QTimer* _scriptRequestTimeout { nullptr }; @@ -107,7 +107,7 @@ private: int _numAvatarSoundSentBytes = 0; bool _isAvatar = false; QTimer* _avatarIdentityTimer = nullptr; - QTimer* _avatarViewTimer = nullptr; + QTimer* _avatarQueryTimer = nullptr; QHash _outgoingScriptAudioSequenceNumbers; AudioGate _audioGate; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d14af685f0..f9d048b6ac 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5682,7 +5682,7 @@ void Application::update(float deltaTime) { if (DependencyManager::get()->shouldRenderEntities()) { queryOctree(NodeType::EntityServer, PacketType::EntityQuery); } - sendAvatarViewFrustum(); + queryAvatars(); _lastQueriedViews = _conicalViews; _lastQueriedTime = now; @@ -5857,7 +5857,7 @@ void Application::update(float deltaTime) { } } -void Application::sendAvatarViewFrustum() { +void Application::queryAvatars() { auto avatarPacket = NLPacket::create(PacketType::AvatarQuery); auto destinationBuffer = reinterpret_cast(avatarPacket->getPayload()); unsigned char* bufferStart = destinationBuffer; diff --git a/interface/src/Application.h b/interface/src/Application.h index 6d749f9458..4a9c293237 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -492,9 +492,9 @@ private: void updateDialogs(float deltaTime) const; void queryOctree(NodeType_t serverType, PacketType packetType); + void queryAvatars(); int sendNackPackets(); - void sendAvatarViewFrustum(); std::shared_ptr getMyAvatar() const; From 487a63025f0681d52f032e85fd4530468392d6e0 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 1 May 2018 19:11:00 -0700 Subject: [PATCH 138/174] Fix warning --- assignment-client/src/avatars/AvatarMixerClientData.cpp | 2 +- assignment-client/src/avatars/AvatarMixerClientData.h | 2 +- interface/src/Application.cpp | 2 +- libraries/octree/src/OctreeQuery.cpp | 2 +- tests/render-perf/src/main.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index aa93fc9e08..d5a8b37742 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -126,7 +126,7 @@ void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, } } -void AvatarMixerClientData::readViewFrustumPacket(QByteArray message) { +void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) { _currentViewFrustums.clear(); auto sourceBuffer = reinterpret_cast(message.constData()); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index f3b2b587ee..e038e81505 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -98,7 +98,7 @@ public: void removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other); void ignoreOther(SharedNodePointer self, SharedNodePointer other); - void readViewFrustumPacket(QByteArray message); + void readViewFrustumPacket(const QByteArray& message); bool otherAvatarInView(const AABox& otherAvatarBox); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f9d048b6ac..d3c75219c5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5862,7 +5862,7 @@ void Application::queryAvatars() { auto destinationBuffer = reinterpret_cast(avatarPacket->getPayload()); unsigned char* bufferStart = destinationBuffer; - uint8_t numFrustums = _conicalViews.size(); + uint8_t numFrustums = (uint8_t)_conicalViews.size(); memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums)); destinationBuffer += sizeof(numFrustums); diff --git a/libraries/octree/src/OctreeQuery.cpp b/libraries/octree/src/OctreeQuery.cpp index 072774f0f5..3f730d4458 100644 --- a/libraries/octree/src/OctreeQuery.cpp +++ b/libraries/octree/src/OctreeQuery.cpp @@ -35,7 +35,7 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += sizeof(_connectionID); // Number of frustums - uint8_t numFrustums = _conicalViews.size(); + uint8_t numFrustums = (uint8_t)_conicalViews.size(); memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums)); destinationBuffer += sizeof(numFrustums); diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 2e72d9cead..33aea6dcc9 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -443,8 +443,7 @@ protected: } const ConicalViewFrustums& getConicalViews() const override { - assert(false); - return ConicalViewFrustums(); + return _view; } QThread* getMainThread() override { @@ -1122,6 +1121,7 @@ private: graphics::LightPointer _globalLight { std::make_shared() }; bool _ready { false }; EntitySimulationPointer _entitySimulation; + ConicalViewFrustums _view; QStringList _commands; QString _commandPath; From 73ce02ce75098cae634664151b11c6f28b8508d6 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 4 May 2018 07:56:44 -0700 Subject: [PATCH 139/174] Fix asan warnings in byte-unpacking functions --- libraries/shared/src/GLMHelpers.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 72710a6a7d..e963345ecd 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -76,13 +76,15 @@ glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) { // Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix) { - int16_t outVal = (int16_t)(scalar * (float)(1 << radix)); - memcpy(buffer, &outVal, sizeof(uint16_t)); - return sizeof(uint16_t); + int16_t twoByteFixed = (int16_t)(scalar * (float)(1 << radix)); + memcpy(buffer, &twoByteFixed, sizeof(int16_t)); + return sizeof(int16_t); } int unpackFloatScalarFromSignedTwoByteFixed(const int16_t* byteFixedPointer, float* destinationPointer, int radix) { - *destinationPointer = *byteFixedPointer / (float)(1 << radix); + int16_t twoByteFixed; + memcpy(&twoByteFixed, byteFixedPointer, sizeof(int16_t)); + *destinationPointer = twoByteFixed / (float)(1 << radix); return sizeof(int16_t); } @@ -102,18 +104,19 @@ int unpackFloatVec3FromSignedTwoByteFixed(const unsigned char* sourceBuffer, glm return sourceBuffer - startPosition; } - int packFloatAngleToTwoByte(unsigned char* buffer, float degrees) { const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0f); - uint16_t angleHolder = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO); - memcpy(buffer, &angleHolder, sizeof(uint16_t)); + uint16_t twoByteAngle = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO); + memcpy(buffer, &twoByteAngle, sizeof(uint16_t)); return sizeof(uint16_t); } int unpackFloatAngleFromTwoByte(const uint16_t* byteAnglePointer, float* destinationPointer) { - *destinationPointer = (*byteAnglePointer / (float) std::numeric_limits::max()) * 360.0f - 180.0f; + uint16_t twoByteAngle; + memcpy(&twoByteAngle, byteAnglePointer, sizeof(uint16_t)); + *destinationPointer = (twoByteAngle / (float) std::numeric_limits::max()) * 360.0f - 180.0f; return sizeof(uint16_t); } From a57c72df6e4754e497f38827bfa888f954325212 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 08:53:49 -0700 Subject: [PATCH 140/174] fix entity highlighting during edit mode --- .../controllers/controllerModules/mouseHighlightEntities.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 86c96fcf6b..3180e58e2c 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -12,10 +12,11 @@ /* jslint bitwise: true */ -/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar*/ +/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar, isInEditMode*/ (function() { + Script.include("/~/system/libraries/utils.js"); var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); function MouseHighlightEntities() { @@ -39,7 +40,7 @@ dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - } else if (!this.grabbedEntity) { + } else if (!this.grabbedEntity && !isInEditMode()) { var pickResult = controllerData.mouseRayPick; if (pickResult.type === Picks.INTERSECTED_ENTITY) { var targetEntityID = pickResult.objectID; From d44882e6dc94a1bc96256b01bfd6915d64fb1b0e Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 08:53:49 -0700 Subject: [PATCH 141/174] fix entity highlighting during edit mode --- .../controllers/controllerModules/mouseHighlightEntities.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 86c96fcf6b..3180e58e2c 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -12,10 +12,11 @@ /* jslint bitwise: true */ -/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar*/ +/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar, isInEditMode*/ (function() { + Script.include("/~/system/libraries/utils.js"); var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); function MouseHighlightEntities() { @@ -39,7 +40,7 @@ dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - } else if (!this.grabbedEntity) { + } else if (!this.grabbedEntity && !isInEditMode()) { var pickResult = controllerData.mouseRayPick; if (pickResult.type === Picks.INTERSECTED_ENTITY) { var targetEntityID = pickResult.objectID; From e48d39ec38c3012b019e928bf05718dc23d9ba1d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 4 May 2018 10:10:48 -0700 Subject: [PATCH 142/174] MS14758: Fix avatar reset when gifting worn avatar --- interface/resources/qml/hifi/commerce/purchases/Purchases.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 6b48f8d51d..d79b8d09fa 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -729,7 +729,7 @@ Rectangle { } lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = function() { - MyAvatar.skeletonModelURL = ''; + MyAvatar.useFullAvatarURL(''); root.activeView = "giftAsset"; lightboxPopup.visible = false; }; From ac0fe620869535d3f49d2cc7d443432db174a409 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 May 2018 10:41:52 -0700 Subject: [PATCH 143/174] Make ModelBaker ktx extension check case-insensitive --- libraries/baking/src/ModelBaker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index ee26b94b81..ac332f4ceb 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -246,9 +246,9 @@ bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMe QString ModelBaker::compressTexture(QString modelTextureFileName, image::TextureUsage::Type textureType) { - QFileInfo modelTextureFileInfo{ modelTextureFileName.replace("\\", "/") }; + QFileInfo modelTextureFileInfo { modelTextureFileName.replace("\\", "/") }; - if (modelTextureFileInfo.suffix() == BAKED_TEXTURE_KTX_EXT.mid(1)) { + if (modelTextureFileInfo.suffix().toLower() == BAKED_TEXTURE_KTX_EXT.mid(1)) { // re-baking a model that already references baked textures // this is an error - return from here handleError("Cannot re-bake a file that already references compressed textures"); From fc3fd75100fdf0d6a147492b911e1b937e73e1e6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 May 2018 10:42:19 -0700 Subject: [PATCH 144/174] Fix TextureMeta::deserialize not handling json parse errors --- libraries/ktx/src/TextureMeta.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/ktx/src/TextureMeta.cpp b/libraries/ktx/src/TextureMeta.cpp index 88235d8a4b..3a2abf24c4 100644 --- a/libraries/ktx/src/TextureMeta.cpp +++ b/libraries/ktx/src/TextureMeta.cpp @@ -11,6 +11,7 @@ #include "TextureMeta.h" +#include #include #include @@ -19,7 +20,12 @@ const QString TEXTURE_META_EXTENSION = ".texmeta.json"; bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) { QJsonParseError error; auto doc = QJsonDocument::fromJson(data, &error); + if (error.error != QJsonParseError::NoError) { + qDebug() << "Failed to parse TextureMeta:" << error.errorString(); + return false; + } if (!doc.isObject()) { + qDebug() << "Unable to process TextureMeta: top-level value is not an Object"; return false; } From e1d218bb57d11ed2b83003ab005dbc6fcb30f6b9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 May 2018 11:25:11 -0700 Subject: [PATCH 145/174] Bump asset packet version for texture meta --- libraries/networking/src/udt/PacketHeaders.cpp | 3 +-- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 98b0e1d892..9eae01cefa 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -59,11 +59,10 @@ PacketVersion versionForPacketType(PacketType packetType) { return 17; case PacketType::AssetMappingOperation: case PacketType::AssetMappingOperationReply: - return static_cast(AssetServerPacketVersion::RedirectedMappings); case PacketType::AssetGetInfo: case PacketType::AssetGet: case PacketType::AssetUpload: - return static_cast(AssetServerPacketVersion::RangeRequestSupport); + return static_cast(AssetServerPacketVersion::BakingTextureMeta); case PacketType::NodeIgnoreRequest: return 18; // Introduction of node ignore request (which replaced an unused packet tpye) diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index e6b133c158..20d98ca2d1 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -250,7 +250,8 @@ enum class EntityQueryPacketVersion: PacketVersion { enum class AssetServerPacketVersion: PacketVersion { VegasCongestionControl = 19, RangeRequestSupport, - RedirectedMappings + RedirectedMappings, + BakingTextureMeta }; enum class AvatarMixerPacketVersion : PacketVersion { From a35517d9851aad3ea1c324840912670a3c54bcd0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 5 May 2018 07:05:10 +1200 Subject: [PATCH 146/174] Fix JSDoc for Users.requestUsernameFromID --- .../script-engine/src/UsersScriptingInterface.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index f214c3f11c..e80d38239f 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -106,10 +106,11 @@ public slots: void mute(const QUuid& nodeID); /**jsdoc - * Get the user name and machine fingerprint associated with the given UUID. This will only do anything if you're an admin - * of the domain you're in. - * @function Users.getUsernameFromID - * @param {Uuid} nodeID The node or session ID of the user whose username you want. + * Request the user name and machine fingerprint associated with the given UUID. The user name will be returned in a + * {@link Users.usernameFromIDReply|usernameFromIDReply} signal. This will only do anything if you're an admin of the domain + * you're in. + * @function Users.requestUsernameFromID + * @param {Uuid} nodeID The node or session ID of the user whose user name you want. */ void requestUsernameFromID(const QUuid& nodeID); @@ -170,7 +171,8 @@ signals: void enteredIgnoreRadius(); /**jsdoc - * Notifies scripts of the user name and machine fingerprint associated with a UUID. + * Triggered in response to a {@link Users.requestUsernameFromID|requestUsernameFromID} call. Provides the user name and + * machine fingerprint associated with a UUID. * Username and machineFingerprint will be their default constructor output if the requesting user isn't an admin. * @function Users.usernameFromIDReply * @param {Uuid} nodeID From aef5ea093604bc2685f319a9e835ba915323f6be Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 4 May 2018 12:30:13 -0700 Subject: [PATCH 147/174] Correct usage of the test script URL. --- interface/src/Application.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 54f1ba2606..fc1602e2e3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1022,7 +1022,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); - if (QFileInfo(testScriptPath).exists()) { + + // If the URL scheme is "http(s)" then use as is, else - treat it as a local file + // This is done so as not break previous command line scripts + if (testScriptPath.left(4) == "http") { + setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath)); + } else if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); } From 81df7a1293516de182f2b86ae289f00aa97d9091 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 4 May 2018 12:41:39 -0700 Subject: [PATCH 148/174] Fix texture leak in QML surface test --- tests/qml/src/main.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp index 349ac55d88..d983353893 100644 --- a/tests/qml/src/main.cpp +++ b/tests/qml/src/main.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -88,7 +88,7 @@ private: OffscreenGLCanvas _sharedContext; std::array, DIVISIONS_X> _surfaces; - QOpenGLFunctions_4_5_Core _glf; + QOpenGLFunctions_4_1_Core _glf; std::function _discardLamdba; QSize _size; size_t _surfaceCount{ 0 }; @@ -145,7 +145,7 @@ void TestWindow::initGl() { gl::initModuleGl(); _glf.initializeOpenGLFunctions(); - _glf.glCreateFramebuffers(1, &_fbo); + _glf.glGenFramebuffers(1, &_fbo); if (!_sharedContext.create(&_glContext) || !_sharedContext.makeCurrent()) { qFatal("Unable to intialize Shared GL context"); @@ -196,6 +196,12 @@ void TestWindow::buildSurface(QmlInfo& qmlInfo, bool video) { void TestWindow::destroySurface(QmlInfo& qmlInfo) { auto& surface = qmlInfo.surface; + auto& currentTexture = qmlInfo.texture; + if (currentTexture) { + auto readFence = _glf.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glFlush(); + _discardLamdba(currentTexture, readFence); + } auto webView = surface->getRootItem(); if (webView) { // stop loading @@ -274,16 +280,19 @@ void TestWindow::draw() { if (!qmlInfo.surface || !qmlInfo.texture) { continue; } - _glf.glNamedFramebufferTexture(_fbo, GL_COLOR_ATTACHMENT0, qmlInfo.texture, 0); - _glf.glBlitNamedFramebuffer(_fbo, 0, - // src coordinates - 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1, - // dst coordinates - incrementX * x, incrementY * y, incrementX * (x + 1), incrementY * (y + 1), - // blit mask and filter - GL_COLOR_BUFFER_BIT, GL_NEAREST); + _glf.glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo); + _glf.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, qmlInfo.texture, 0); + _glf.glBlitFramebuffer( + // src coordinates + 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1, + // dst coordinates + incrementX * x, incrementY * y, incrementX * (x + 1), incrementY * (y + 1), + // blit mask and filter + GL_COLOR_BUFFER_BIT, GL_NEAREST); } } + _glf.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + _glf.glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); _glContext.swapBuffers(this); } From 53fe0bc616c36ebece838e0e00cf84575addfcf7 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 4 May 2018 14:08:21 -0700 Subject: [PATCH 149/174] MS14699: Prevent Wallet passcode from being sticky in certain cases --- .../qml/hifi/commerce/wallet/PassphraseModal.qml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index 1cada9789b..c4abd40d2a 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -47,6 +47,13 @@ Item { onWalletAuthenticatedStatusResult: { submitPassphraseInputButton.enabled = true; + + // It's not possible to auth with a blank passphrase, + // so bail early if we get this signal without anything in the passphrase field + if (passphraseField.text === "") { + return; + } + if (!isAuthenticated) { errorText.text = "Authentication failed - please try again."; passphraseField.error = true; @@ -211,6 +218,10 @@ Item { error = false; focus = true; forceActiveFocus(); + } else { + showPassphrase.checked = false; + passphraseField.text = ""; + error = false; } } From 2c2b74f4c8a965ee7f0171f9d9685d09b9c75a4e Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 4 May 2018 14:13:14 -0700 Subject: [PATCH 150/174] Removed unused variable. --- tools/auto-tester/src/ui/AutoTester.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index e0f92664ef..59fe5d9de2 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -94,7 +94,6 @@ void AutoTester::saveImage(int index) { QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); - int sdf = pixmap.width(); QImage image = pixmap.toImage(); image = image.convertToFormat(QImage::Format_ARGB32); From 6414fcaae568b31e43c89b72bbc7405d4eb5e88a Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 14:20:17 -0700 Subject: [PATCH 151/174] fix-another-highlighting-issue --- .../controllerModules/highlightNearbyEntities.js | 11 ++++++++++- .../controllers/controllerModules/inEditMode.js | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index 32e1b4300d..bc09ebee7a 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -56,6 +56,12 @@ return canGrabEntity; }; + this.clearAll = function() { + this.highlightedEntities.forEach(function(entity) { + dispatcherUtils.unhighlightTargetEntity(entity); + }); + }; + this.hasHyperLink = function(props) { return (props.href !== "" && props.href !== undefined); }; @@ -121,7 +127,6 @@ if (channel === 'Hifi-unhighlight-entity') { try { data = JSON.parse(message); - var hand = data.hand; if (hand === dispatcherUtils.LEFT_HAND) { leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); @@ -131,6 +136,9 @@ } catch (e) { print("Failed to parse message"); } + } else if (channel === 'Hifi-unhighlight-all') { + leftHighlightNearbyEntities.clearAll(); + rightHighlightNearbyEntities.clearAll(); } } }; @@ -145,6 +153,7 @@ dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); } Messages.subscribe('Hifi-unhighlight-entity'); + Messages.subscribe('Hifi-unhighlight-all'); Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index f7e86f9042..3ad7902d71 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -78,6 +78,7 @@ Script.include("/~/system/libraries/utils.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) { this.triggerClicked = false; } + Messages.sendLocalMessage('Hifi-unhighlight-all', ''); return makeRunningValues(true, [], []); } this.triggerClicked = false; From 176d69444f461cdb16d3d26b9ae0f06e17db0476 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 14:20:17 -0700 Subject: [PATCH 152/174] fix-another-highlighting-issue --- .../controllerModules/highlightNearbyEntities.js | 11 ++++++++++- .../controllers/controllerModules/inEditMode.js | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index 32e1b4300d..bc09ebee7a 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -56,6 +56,12 @@ return canGrabEntity; }; + this.clearAll = function() { + this.highlightedEntities.forEach(function(entity) { + dispatcherUtils.unhighlightTargetEntity(entity); + }); + }; + this.hasHyperLink = function(props) { return (props.href !== "" && props.href !== undefined); }; @@ -121,7 +127,6 @@ if (channel === 'Hifi-unhighlight-entity') { try { data = JSON.parse(message); - var hand = data.hand; if (hand === dispatcherUtils.LEFT_HAND) { leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); @@ -131,6 +136,9 @@ } catch (e) { print("Failed to parse message"); } + } else if (channel === 'Hifi-unhighlight-all') { + leftHighlightNearbyEntities.clearAll(); + rightHighlightNearbyEntities.clearAll(); } } }; @@ -145,6 +153,7 @@ dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); } Messages.subscribe('Hifi-unhighlight-entity'); + Messages.subscribe('Hifi-unhighlight-all'); Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index f7e86f9042..3ad7902d71 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -78,6 +78,7 @@ Script.include("/~/system/libraries/utils.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) { this.triggerClicked = false; } + Messages.sendLocalMessage('Hifi-unhighlight-all', ''); return makeRunningValues(true, [], []); } this.triggerClicked = false; From 0e92bb41bfcfeb9fe4c9f114706a8d721fb2a7fd Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 14:20:17 -0700 Subject: [PATCH 153/174] fix-another-highlighting-issue --- .../controllerModules/highlightNearbyEntities.js | 11 ++++++++++- .../controllers/controllerModules/inEditMode.js | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index 32e1b4300d..bc09ebee7a 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -56,6 +56,12 @@ return canGrabEntity; }; + this.clearAll = function() { + this.highlightedEntities.forEach(function(entity) { + dispatcherUtils.unhighlightTargetEntity(entity); + }); + }; + this.hasHyperLink = function(props) { return (props.href !== "" && props.href !== undefined); }; @@ -121,7 +127,6 @@ if (channel === 'Hifi-unhighlight-entity') { try { data = JSON.parse(message); - var hand = data.hand; if (hand === dispatcherUtils.LEFT_HAND) { leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); @@ -131,6 +136,9 @@ } catch (e) { print("Failed to parse message"); } + } else if (channel === 'Hifi-unhighlight-all') { + leftHighlightNearbyEntities.clearAll(); + rightHighlightNearbyEntities.clearAll(); } } }; @@ -145,6 +153,7 @@ dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); } Messages.subscribe('Hifi-unhighlight-entity'); + Messages.subscribe('Hifi-unhighlight-all'); Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index f7e86f9042..3ad7902d71 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -78,6 +78,7 @@ Script.include("/~/system/libraries/utils.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) { this.triggerClicked = false; } + Messages.sendLocalMessage('Hifi-unhighlight-all', ''); return makeRunningValues(true, [], []); } this.triggerClicked = false; From b04c5bd0db04688dfa965fe3aa90d79ab2bbf1fa Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 4 May 2018 14:43:16 -0700 Subject: [PATCH 154/174] CR --- interface/src/Application.cpp | 16 ++++++++-------- interface/src/Application.h | 8 ++++++-- libraries/entities/src/EntityPriorityQueue.h | 4 ++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d3c75219c5..0d8ab13a9f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -967,7 +967,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _entitySimulation(new PhysicalEntitySimulation()), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), _entityClipboard(new EntityTree()), - _lastQueriedTime(usecTimestampNow()), _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), _hmdTabletScale("hmdTabletScale", DEFAULT_HMD_TABLET_SCALE_PERCENT), @@ -5084,7 +5083,7 @@ void Application::reloadResourceCaches() { resetPhysicsReadyInformation(); // Query the octree to refresh everything in view - _lastQueriedTime = 0; + _queryExpiry = SteadyClock::now(); _octreeQuery.incrementConnectionID(); queryOctree(NodeType::EntityServer, PacketType::EntityQuery); @@ -5660,9 +5659,6 @@ void Application::update(float deltaTime) { PROFILE_RANGE_EX(app, "QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("queryOctree"); QMutexLocker viewLocker(&_viewMutex); - quint64 sinceLastQuery = now - _lastQueriedTime; - const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; - bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY; bool viewIsDifferentEnough = false; if (_conicalViews.size() == _lastQueriedViews.size()) { @@ -5678,14 +5674,16 @@ void Application::update(float deltaTime) { // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it - if (queryIsDue || viewIsDifferentEnough) { + static const std::chrono::seconds MIN_PERIOD_BETWEEN_QUERIES { 3 }; + auto now = SteadyClock::now(); + if (now > _queryExpiry || viewIsDifferentEnough) { if (DependencyManager::get()->shouldRenderEntities()) { queryOctree(NodeType::EntityServer, PacketType::EntityQuery); } queryAvatars(); _lastQueriedViews = _conicalViews; - _lastQueriedTime = now; + _queryExpiry = now + MIN_PERIOD_BETWEEN_QUERIES; } } @@ -6142,7 +6140,7 @@ void Application::nodeActivated(SharedNodePointer node) { // If we get a new EntityServer activated, reset lastQueried time // so we will do a proper query during update if (node->getType() == NodeType::EntityServer) { - _lastQueriedTime = 0; + _queryExpiry = SteadyClock::now(); _octreeQuery.incrementConnectionID(); } @@ -6151,6 +6149,8 @@ void Application::nodeActivated(SharedNodePointer node) { } if (node->getType() == NodeType::AvatarMixer) { + _queryExpiry = SteadyClock::now(); + // new avatar mixer, send off our identity packet on next update loop // Reset skeletonModelUrl if the last server modified our choice. // Override the avatar url (but not model name) here too. diff --git a/interface/src/Application.h b/interface/src/Application.h index 4a9c293237..654b5c797b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -111,7 +111,8 @@ class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface, public AbstractUriHandler, - public PluginContainer { + public PluginContainer +{ Q_OBJECT // TODO? Get rid of those @@ -579,7 +580,10 @@ private: ConicalViewFrustums _conicalViews; ConicalViewFrustums _lastQueriedViews; // last views used to query servers - quint64 _lastQueriedTime; + + using SteadyClock = std::chrono::steady_clock; + using TimePoint = SteadyClock::time_point; + TimePoint _queryExpiry; OctreeQuery _octreeQuery { true }; // NodeData derived class for querying octee cells from octree servers diff --git a/libraries/entities/src/EntityPriorityQueue.h b/libraries/entities/src/EntityPriorityQueue.h index 354cd70af3..339676d237 100644 --- a/libraries/entities/src/EntityPriorityQueue.h +++ b/libraries/entities/src/EntityPriorityQueue.h @@ -20,8 +20,8 @@ // PrioritizedEntity is a placeholder in a sorted queue. class PrioritizedEntity { public: - static constexpr float DO_NOT_SEND { -1.0e-6f }; - static constexpr float FORCE_REMOVE { -1.0e-5f }; + static constexpr float DO_NOT_SEND { -1.0e6f }; + static constexpr float FORCE_REMOVE { -1.0e5f }; static constexpr float WHEN_IN_DOUBT_PRIORITY { 1.0f }; PrioritizedEntity(EntityItemPointer entity, float priority, bool forceRemove = false) : _weakEntity(entity), _rawEntityPointer(entity.get()), _priority(priority), _forceRemove(forceRemove) {} From ad60a791803c41ddfac08aef31d7f0ed3c144d46 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 4 May 2018 14:43:28 -0700 Subject: [PATCH 155/174] Fix for android builds --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0d8ab13a9f..0a76c8f475 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5226,9 +5226,8 @@ void Application::updateSecondaryCameraViewFrustum() { auto renderConfig = _renderEngine->getConfiguration(); assert(renderConfig); auto camera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); - assert(camera); - if (!camera->isEnabled()) { + if (!camera || !camera->isEnabled()) { return; } From cc4d04aaef8d7e1aae0950c4187e26211d7842f1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 4 May 2018 14:45:57 -0700 Subject: [PATCH 156/174] experimenting --- tests/qml/src/main.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp index d983353893..d70bb52dde 100644 --- a/tests/qml/src/main.cpp +++ b/tests/qml/src/main.cpp @@ -109,14 +109,6 @@ TestWindow::TestWindow() { Setting::init(); setSurfaceType(QSurface::OpenGLSurface); - QSurfaceFormat format; - format.setDepthBufferSize(24); - format.setStencilBufferSize(8); - format.setVersion(4, 5); - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - format.setOption(QSurfaceFormat::DebugContext); - QSurfaceFormat::setDefaultFormat(format); - setFormat(format); qmlRegisterType("Hifi", 1, 0, "TestItem"); @@ -301,6 +293,16 @@ void TestWindow::resizeEvent(QResizeEvent* ev) { } int main(int argc, char** argv) { + + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + format.setVersion(4, 1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + format.setOption(QSurfaceFormat::DebugContext); + QSurfaceFormat::setDefaultFormat(format); + // setFormat(format); + QGuiApplication app(argc, argv); TestWindow window; return app.exec(); From 4ebed7605c979eed603a1d7738730537708e3359 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 4 May 2018 10:10:48 -0700 Subject: [PATCH 157/174] MS14758: Fix avatar reset when gifting worn avatar --- interface/resources/qml/hifi/commerce/purchases/Purchases.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 08e3e7a552..b54a931c51 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -582,7 +582,7 @@ Rectangle { } lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = function() { - MyAvatar.skeletonModelURL = ''; + MyAvatar.useFullAvatarURL(''); root.activeView = "giftAsset"; lightboxPopup.visible = false; }; From 8480bb962b99bdcf2a5b3e457d9cd36106889b68 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 3 May 2018 13:51:50 -0700 Subject: [PATCH 158/174] Fix for crash deep in QML after useFullAvatarURL Here we avoid calling FSTReader::downloadMapping() from within MyAvatar::useFullAvatarURL(). This prevents the error case where a QEventLoop is entered during QML execution. --- interface/src/avatar/MyAvatar.cpp | 18 +++++++++++------- .../src/model-networking/ModelCache.cpp | 14 +++++++++----- .../src/model-networking/ModelCache.h | 2 ++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 249a765d92..3eef1dac3c 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1473,6 +1473,15 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { std::shared_ptr skeletonConnection = std::make_shared(); *skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() { if (skeletonModelChangeCount == _skeletonModelChangeCount) { + + if (_fullAvatarModelName.isEmpty()) { + // Store the FST file name into preferences + const auto& mapping = _skeletonModel->getGeometry()->getMapping(); + if (mapping.value("name").isValid()) { + _fullAvatarModelName = mapping.value("name").toString(); + } + } + initHeadBones(); _skeletonModel->setCauterizeBoneSet(_headBoneSet); _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); @@ -1535,12 +1544,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN if (_fullAvatarURLFromPreferences != fullAvatarURL) { _fullAvatarURLFromPreferences = fullAvatarURL; - if (modelName.isEmpty()) { - QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString()); - _fullAvatarModelName = fullAvatarFST["name"].toString(); - } else { - _fullAvatarModelName = modelName; - } + _fullAvatarModelName = modelName; } const QString& urlString = fullAvatarURL.toString(); @@ -1548,8 +1552,8 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN setSkeletonModelURL(fullAvatarURL); UserActivityLogger::getInstance().changedModel("skeleton", urlString); } + markIdentityDataChanged(); - } void MyAvatar::setAttachmentData(const QVector& attachmentData) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index f17cdbb7e8..939168f1b1 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -63,16 +63,18 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryMappingResource::downloadFinished", _url.toString(), { { "url", _url.toString() } }); - auto mapping = FSTReader::readMapping(data); + // store parsed contents of FST file + _mapping = FSTReader::readMapping(data); + + QString filename = _mapping.value("filename").toString(); - QString filename = mapping.value("filename").toString(); if (filename.isNull()) { qCDebug(modelnetworking) << "Mapping file" << _url << "has no \"filename\" field"; finishedLoading(false); } else { QUrl url = _url.resolved(filename); - QString texdir = mapping.value(TEXDIR_FIELD).toString(); + QString texdir = _mapping.value(TEXDIR_FIELD).toString(); if (!texdir.isNull()) { if (!texdir.endsWith('/')) { texdir += '/'; @@ -82,7 +84,8 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { _textureBaseUrl = url.resolved(QUrl(".")); } - auto animGraphVariant = mapping.value("animGraphUrl"); + auto animGraphVariant = _mapping.value("animGraphUrl"); + if (animGraphVariant.isValid()) { QUrl fstUrl(animGraphVariant.toString()); if (fstUrl.isValid()) { @@ -95,7 +98,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { } auto modelCache = DependencyManager::get(); - GeometryExtra extra{ mapping, _textureBaseUrl, false }; + GeometryExtra extra{ _mapping, _textureBaseUrl, false }; // Get the raw GeometryResource _geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast(); @@ -362,6 +365,7 @@ Geometry::Geometry(const Geometry& geometry) { } _animGraphOverrideUrl = geometry._animGraphOverrideUrl; + _mapping = geometry._mapping; } void Geometry::setTextures(const QVariantMap& textureMap) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 9532f39ce0..6978e0077e 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -55,6 +55,7 @@ public: virtual bool areTexturesLoaded() const; const QUrl& getAnimGraphOverrideUrl() const { return _animGraphOverrideUrl; } + const QVariantHash& getMapping() const { return _mapping; } protected: friend class GeometryMappingResource; @@ -68,6 +69,7 @@ protected: NetworkMaterials _materials; QUrl _animGraphOverrideUrl; + QVariantHash _mapping; // parsed contents of FST file. private: mutable bool _areTexturesLoaded { false }; From da9fb9c751a20b8d915ed657c5056cb4fe030d37 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 26 Apr 2018 14:27:45 -0700 Subject: [PATCH 159/174] Fix non self-sufficient headers --- assignment-client/src/AssignmentClient.cpp | 14 ++++---- .../src/AssignmentClientMonitor.cpp | 3 +- assignment-client/src/AssignmentDynamic.cpp | 4 +-- assignment-client/src/AssignmentFactory.cpp | 3 +- .../src/audio/AudioMixerSlavePool.cpp | 4 +-- .../src/audio/AvatarAudioStream.cpp | 3 +- assignment-client/src/avatars/AvatarMixer.cpp | 4 +-- .../src/avatars/AvatarMixerClientData.cpp | 4 +-- .../src/avatars/AvatarMixerSlave.cpp | 4 +-- .../src/avatars/AvatarMixerSlave.h | 2 ++ .../src/avatars/AvatarMixerSlavePool.cpp | 4 +-- .../src/avatars/ScriptableAvatar.cpp | 3 +- .../src/entities/EntityServer.cpp | 8 +++-- .../src/messages/MessagesMixer.cpp | 3 +- .../octree/OctreeInboundPacketProcessor.cpp | 3 +- .../src/octree/OctreeSendThread.cpp | 3 +- domain-server/src/DomainServerNodeData.cpp | 4 +-- domain-server/src/DomainServerNodeData.h | 1 + .../src/DomainServerWebSessionData.cpp | 4 +-- gvr-interface/src/Client.cpp | 6 ++-- gvr-interface/src/GVRInterface.cpp | 4 +-- gvr-interface/src/GVRMainWindow.cpp | 4 +-- gvr-interface/src/LoginDialog.cpp | 6 ++-- gvr-interface/src/RenderingClient.cpp | 4 +-- interface/src/AvatarBookmarks.cpp | 3 +- interface/src/Bookmarks.cpp | 4 +-- interface/src/DiscoverabilityManager.cpp | 6 ++-- interface/src/DiscoverabilityManager.h | 4 +++ interface/src/GLCanvas.cpp | 4 +-- interface/src/InterfaceDynamicFactory.cpp | 5 +-- interface/src/InterfaceParentFinder.cpp | 8 ++--- interface/src/LODManager.cpp | 4 +-- interface/src/LocationBookmarks.cpp | 6 ++-- interface/src/Menu.cpp | 4 +-- interface/src/ModelPackager.cpp | 4 +-- interface/src/ModelPackager.h | 2 ++ interface/src/ModelPropertiesDialog.cpp | 4 +-- interface/src/ModelSelector.cpp | 6 ++-- interface/src/SecondaryCamera.cpp | 13 +++++--- interface/src/SecondaryCamera.h | 2 ++ interface/src/SpeechRecognizer.cpp | 3 +- interface/src/SpeechRecognizer.mm | 4 +-- interface/src/UIUtil.cpp | 4 +-- interface/src/audio/AudioScope.cpp | 4 +-- interface/src/avatar/AvatarManager.cpp | 3 +- interface/src/commerce/Ledger.cpp | 9 ++++-- interface/src/commerce/Wallet.cpp | 32 +++++++++---------- interface/src/networking/CloseEventSender.cpp | 4 +-- .../src/octree/OctreePacketProcessor.cpp | 3 +- .../AccountServicesScriptingInterface.cpp | 4 +-- .../AccountServicesScriptingInterface.h | 2 ++ interface/src/scripting/AudioDevices.cpp | 5 ++- .../GooglePolyScriptingInterface.cpp | 4 +-- ...lessVoiceRecognitionScriptingInterface.cpp | 7 ++-- interface/src/ui/DomainConnectionDialog.cpp | 4 +-- interface/src/ui/HMDToolsDialog.cpp | 5 +-- interface/src/ui/LodToolsDialog.cpp | 3 +- interface/src/ui/ModelsBrowser.cpp | 4 +-- interface/src/ui/OctreeStatsDialog.cpp | 5 ++- interface/src/ui/OctreeStatsDialog.h | 3 +- interface/src/ui/OctreeStatsProvider.cpp | 6 ++-- interface/src/ui/OverlayConductor.cpp | 3 +- interface/src/ui/OverlayConductor.h | 6 ++-- interface/src/ui/Snapshot.cpp | 3 +- interface/src/ui/Snapshot.h | 1 + interface/src/ui/SnapshotAnimated.cpp | 3 +- interface/src/ui/SnapshotUploader.cpp | 5 ++- interface/src/ui/StandAloneJSConsole.cpp | 4 +-- interface/src/ui/TestingDialog.cpp | 4 +-- interface/src/ui/overlays/ModelOverlay.cpp | 3 +- libraries/animation/src/AnimClip.cpp | 3 +- libraries/animation/src/AnimExpression.cpp | 6 ++-- libraries/animation/src/AnimNode.cpp | 3 +- libraries/animation/src/AnimNodeLoader.cpp | 3 +- libraries/animation/src/AnimVariant.cpp | 5 +-- libraries/animation/src/AnimationObject.cpp | 3 +- libraries/audio-client/src/AudioClient.cpp | 4 +-- libraries/audio-client/src/AudioIOStats.cpp | 4 +-- libraries/audio/src/AudioFOA.cpp | 3 +- libraries/audio/src/AudioGate.cpp | 3 +- libraries/audio/src/AudioHRTF.cpp | 3 +- libraries/audio/src/AudioLimiter.cpp | 3 +- libraries/audio/src/AudioReverb.cpp | 4 +-- libraries/audio/src/AudioRingBuffer.cpp | 4 +-- libraries/audio/src/AudioSRC.cpp | 3 +- libraries/audio/src/InboundAudioStream.cpp | 3 +- libraries/audio/src/InjectedAudioStream.cpp | 3 +- libraries/audio/src/Sound.cpp | 4 +-- libraries/avatars/src/AvatarHashMap.cpp | 3 +- libraries/baking/src/Baker.cpp | 4 +-- libraries/baking/src/FBXBaker.cpp | 4 +-- libraries/baking/src/JSBaker.cpp | 3 +- libraries/baking/src/JSBaker.h | 2 ++ libraries/baking/src/OBJBaker.cpp | 3 +- libraries/baking/src/TextureBaker.cpp | 4 +-- libraries/baking/src/TextureBaker.h | 1 + .../src/controllers/DeviceProxy.cpp | 17 ---------- .../controllers/src/controllers/Pose.cpp | 4 +-- .../src/controllers/impl/Mapping.cpp | 15 --------- .../src/controllers/impl/Route.cpp | 15 --------- .../impl/conditionals/EndpointConditional.cpp | 15 --------- .../impl/endpoints/ArrayEndpoint.cpp | 15 --------- .../impl/endpoints/StandardEndpoint.cpp | 15 --------- .../impl/filters/ConstrainToIntegerFilter.cpp | 15 --------- .../ConstrainToPositiveIntegerFilter.cpp | 15 --------- .../controllers/impl/filters/InvertFilter.cpp | 15 --------- .../embedded-webserver/src/HTTPConnection.cpp | 4 +-- .../embedded-webserver/src/HTTPManager.cpp | 3 +- .../src/HTTPSConnection.cpp | 3 +- .../embedded-webserver/src/HTTPSManager.cpp | 4 +-- .../entities/src/DeleteEntityOperator.cpp | 4 +-- libraries/entities/src/DeleteEntityOperator.h | 6 ++++ .../entities/src/EntityDynamicInterface.cpp | 3 +- .../entities/src/EntityDynamicInterface.h | 5 ++- libraries/entities/src/EntityEditFilters.cpp | 2 +- .../entities/src/EntityEditPacketSender.cpp | 8 +++-- .../entities/src/EntityItemProperties.cpp | 16 ++++++---- libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityTree.h | 6 ++-- libraries/entities/src/EntityTypes.cpp | 3 +- libraries/entities/src/HazePropertyGroup.cpp | 3 +- libraries/entities/src/LightEntityItem.cpp | 2 +- libraries/entities/src/ModelEntityItem.cpp | 6 ++-- .../entities/src/MovingEntitiesOperator.cpp | 4 +-- .../entities/src/MovingEntitiesOperator.h | 3 +- .../entities/src/ParticleEffectEntityItem.cpp | 3 +- libraries/entities/src/PolyLineEntityItem.cpp | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 2 +- .../entities/src/SkyboxPropertyGroup.cpp | 3 +- libraries/entities/src/SkyboxPropertyGroup.h | 2 ++ libraries/entities/src/TextEntityItem.cpp | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 2 +- libraries/fbx/src/FBXReader.cpp | 3 +- libraries/fbx/src/FSTReader.cpp | 4 +-- libraries/fbx/src/GLTFReader.cpp | 5 +-- .../src/graphics-scripting/ScriptableMesh.cpp | 16 ++++++---- .../graphics-scripting/ScriptableMeshPart.cpp | 15 +++++---- .../graphics-scripting/ScriptableModel.cpp | 5 ++- libraries/graphics/src/graphics/Haze.cpp | 3 +- libraries/networking/src/AddressManager.cpp | 3 +- libraries/networking/src/Assignment.cpp | 9 +++--- libraries/networking/src/AtpReply.cpp | 3 +- .../networking/src/BandwidthRecorder.cpp | 2 +- .../networking/src/DataServerAccountInfo.cpp | 3 +- libraries/networking/src/HifiSockAddr.cpp | 3 +- .../src/LocationScriptingInterface.cpp | 4 +-- .../networking/src/NetworkAccessManager.cpp | 3 +- libraries/networking/src/Node.cpp | 4 +-- libraries/networking/src/OAuthAccessToken.cpp | 4 +-- .../src/OAuthNetworkAccessManager.cpp | 4 +-- libraries/networking/src/PacketSender.cpp | 3 +- .../networking/src/RSAKeypairGenerator.cpp | 4 +-- .../src/ReceivedPacketProcessor.cpp | 3 +- .../networking/src/ReceivedPacketProcessor.h | 4 +++ .../networking/src/ThreadedAssignment.cpp | 4 +-- .../networking/src/UserActivityLogger.cpp | 7 ++-- .../networking/src/WalletTransaction.cpp | 5 ++- .../networking/src/udt/ConnectionStats.cpp | 3 +- libraries/octree/src/Octree.cpp | 3 +- .../octree/src/OctreeEditPacketSender.cpp | 3 +- libraries/octree/src/OctreeElement.cpp | 5 +-- libraries/octree/src/OctreePacketData.cpp | 3 +- libraries/octree/src/OctreePersistThread.cpp | 3 +- libraries/octree/src/OctreeProcessor.cpp | 5 +-- libraries/octree/src/OctreeSceneStats.cpp | 4 +-- .../octree/src/OctreeScriptingInterface.cpp | 4 +-- libraries/physics/src/EntityMotionState.cpp | 3 +- libraries/physics/src/MeshMassProperties.cpp | 4 +-- libraries/physics/src/ObjectAction.cpp | 4 +-- libraries/physics/src/ObjectActionOffset.cpp | 4 +-- libraries/physics/src/ObjectActionTractor.cpp | 4 +-- .../src/ObjectActionTravelOriented.cpp | 3 +- libraries/physics/src/ObjectConstraint.cpp | 4 +-- .../src/ObjectConstraintBallSocket.cpp | 3 +- .../physics/src/ObjectConstraintConeTwist.cpp | 3 +- .../physics/src/ObjectConstraintHinge.cpp | 3 +- .../physics/src/ObjectConstraintSlider.cpp | 3 +- libraries/physics/src/ObjectDynamic.cpp | 4 +-- libraries/physics/src/ObjectMotionState.cpp | 3 +- libraries/physics/src/PhysicsEngine.cpp | 4 +-- libraries/physics/src/ShapeFactory.cpp | 3 +- libraries/physics/src/ShapeManager.cpp | 5 +-- .../physics/src/ThreadSafeDynamicsWorld.cpp | 3 +- .../recording/src/recording/ClipCache.cpp | 3 +- .../src/AmbientOcclusionEffect.cpp | 7 ++-- .../render-utils/src/AntialiasingEffect.cpp | 2 +- libraries/render-utils/src/LightStage.cpp | 4 +-- .../render-utils/src/RenderPipelines.cpp | 6 ++-- libraries/render/src/render/DrawTask.cpp | 6 ++-- libraries/render/src/render/ShapePipeline.cpp | 7 ++-- .../script-engine/src/ArrayBufferClass.cpp | 4 +-- .../src/ArrayBufferPrototype.cpp | 3 +- libraries/script-engine/src/BatchLoader.cpp | 8 +++-- .../src/ConsoleScriptingInterface.cpp | 4 ++- libraries/script-engine/src/DataViewClass.cpp | 6 ++-- .../script-engine/src/DataViewPrototype.cpp | 5 +-- libraries/script-engine/src/EventTypes.cpp | 4 +-- libraries/script-engine/src/KeyEvent.cpp | 4 +-- libraries/script-engine/src/Mat4.cpp | 9 ++++-- .../script-engine/src/MenuItemProperties.cpp | 4 +-- libraries/script-engine/src/MouseEvent.cpp | 6 ++-- libraries/script-engine/src/MouseEvent.h | 5 ++- libraries/script-engine/src/Quat.cpp | 7 ++-- libraries/script-engine/src/Quat.h | 2 ++ .../script-engine/src/ScriptAudioInjector.cpp | 3 +- libraries/script-engine/src/ScriptEngine.cpp | 3 +- libraries/script-engine/src/ScriptUUID.cpp | 3 +- libraries/script-engine/src/ScriptUUID.h | 1 + libraries/script-engine/src/SpatialEvent.cpp | 6 ++-- libraries/script-engine/src/TouchEvent.cpp | 5 ++- libraries/script-engine/src/TouchEvent.h | 7 +++- .../script-engine/src/TypedArrayPrototype.cpp | 4 +-- libraries/script-engine/src/TypedArrays.cpp | 4 +-- .../src/UndoStackScriptingInterface.cpp | 4 +-- libraries/script-engine/src/Vec3.cpp | 7 ++-- .../script-engine/src/WebSocketClass.cpp | 3 +- .../src/WebSocketServerClass.cpp | 3 +- libraries/script-engine/src/WheelEvent.cpp | 8 ++--- libraries/script-engine/src/WheelEvent.h | 6 +++- .../script-engine/src/XMLHttpRequestClass.cpp | 3 +- libraries/shared/src/AACube.cpp | 3 +- libraries/shared/src/CubeProjectedPolygon.cpp | 4 +-- libraries/shared/src/GPUIdent.cpp | 6 ++-- libraries/shared/src/GPUIdent.h | 2 ++ libraries/shared/src/GenericThread.cpp | 5 ++- libraries/shared/src/Gzip.cpp | 3 +- libraries/shared/src/LogUtils.cpp | 4 +-- libraries/shared/src/OctalCode.cpp | 3 +- libraries/shared/src/PIDController.cpp | 9 ++++-- libraries/shared/src/PerfStat.cpp | 4 +-- libraries/shared/src/SimpleMovingAverage.cpp | 3 +- libraries/shared/src/StDev.cpp | 4 +-- libraries/shared/src/StreamUtils.cpp | 4 +-- libraries/shared/src/TriangleSet.cpp | 2 +- .../shared/src/VariantMapToScriptValue.cpp | 5 +-- libraries/shared/src/ViewFrustum.cpp | 6 ++-- libraries/shared/src/shared/StringHelpers.cpp | 4 +-- plugins/pcmCodec/src/PCMCodecManager.cpp | 4 +-- tests/jitter/src/JitterTests.cpp | 4 +-- tests/networking/src/ResourceTests.cpp | 4 +-- .../src/SequenceNumberStatsTests.cpp | 4 +-- tests/octree/src/AABoxCubeTests.cpp | 4 +-- tests/octree/src/ModelTests.cpp | 6 ++-- tests/octree/src/OctreeTests.cpp | 4 +-- tests/physics/src/ShapeInfoTests.cpp | 4 +-- tests/physics/src/ShapeManagerTests.cpp | 5 +-- tests/shared/src/AABoxTests.cpp | 4 +-- tests/shared/src/AACubeTests.cpp | 4 +-- tests/shared/src/DualQuaternionTests.cpp | 4 +-- tests/shared/src/GeometryUtilTests.cpp | 4 +-- tools/ac-client/src/ACClientApp.cpp | 5 +-- tools/atp-client/src/ATPClientApp.cpp | 4 +-- tools/ice-client/src/ICEClientApp.cpp | 5 +-- tools/oven/src/BakerCLI.cpp | 3 +- tools/oven/src/OvenCLIApplication.cpp | 4 +-- tools/oven/src/ui/BakeWidget.cpp | 4 +-- tools/oven/src/ui/DomainBakeWidget.cpp | 4 +-- tools/oven/src/ui/ModelBakeWidget.cpp | 3 +- tools/oven/src/ui/ModesWidget.cpp | 4 +-- tools/oven/src/ui/OvenMainWindow.cpp | 4 +-- tools/oven/src/ui/ResultsWindow.cpp | 4 +-- tools/oven/src/ui/SkyboxBakeWidget.cpp | 6 ++-- tools/vhacd-util/src/VHACDUtilApp.cpp | 5 ++- 263 files changed, 632 insertions(+), 603 deletions(-) delete mode 100644 libraries/controllers/src/controllers/DeviceProxy.cpp delete mode 100644 libraries/controllers/src/controllers/impl/Mapping.cpp delete mode 100644 libraries/controllers/src/controllers/impl/Route.cpp delete mode 100644 libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp delete mode 100644 libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp delete mode 100644 libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp delete mode 100644 libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.cpp delete mode 100644 libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.cpp delete mode 100644 libraries/controllers/src/controllers/impl/filters/InvertFilter.cpp diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index efced972a0..41e42aa0a1 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AssignmentClient.h" + #include #include @@ -32,16 +34,14 @@ #include #include #include - -#include "AssignmentFactory.h" -#include "AssignmentDynamicFactory.h" - -#include "AssignmentClient.h" -#include "AssignmentClientLogging.h" -#include "avatars/ScriptableAvatar.h" #include #include +#include "AssignmentClientLogging.h" +#include "AssignmentDynamicFactory.h" +#include "AssignmentFactory.h" +#include "avatars/ScriptableAvatar.h" + const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client"; const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000; diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 1868ccfafe..2847d4ebf1 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AssignmentClientMonitor.h" + #include #include @@ -19,7 +21,6 @@ #include #include -#include "AssignmentClientMonitor.h" #include "AssignmentClientApp.h" #include "AssignmentClientChildData.h" #include "SharedUtil.h" diff --git a/assignment-client/src/AssignmentDynamic.cpp b/assignment-client/src/AssignmentDynamic.cpp index 7adbd55c39..447097ac74 100644 --- a/assignment-client/src/AssignmentDynamic.cpp +++ b/assignment-client/src/AssignmentDynamic.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "EntitySimulation.h" - #include "AssignmentDynamic.h" +#include "EntitySimulation.h" + AssignmentDynamic::AssignmentDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) : EntityDynamicInterface(type, id), _data(QByteArray()), diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 38eb72649f..405039d833 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AssignmentFactory.h" + #include #include "Agent.h" #include "assets/AssetServer.h" -#include "AssignmentFactory.h" #include "audio/AudioMixer.h" #include "avatars/AvatarMixer.h" #include "entities/EntityServer.h" diff --git a/assignment-client/src/audio/AudioMixerSlavePool.cpp b/assignment-client/src/audio/AudioMixerSlavePool.cpp index e28c96e259..dfe7ef56aa 100644 --- a/assignment-client/src/audio/AudioMixerSlavePool.cpp +++ b/assignment-client/src/audio/AudioMixerSlavePool.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioMixerSlavePool.h" + #include #include -#include "AudioMixerSlavePool.h" - void AudioMixerSlaveThread::run() { while (true) { wait(); diff --git a/assignment-client/src/audio/AvatarAudioStream.cpp b/assignment-client/src/audio/AvatarAudioStream.cpp index 42495b4dd0..22ea8c0617 100644 --- a/assignment-client/src/audio/AvatarAudioStream.cpp +++ b/assignment-client/src/audio/AvatarAudioStream.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarAudioStream.h" + #include #include "AudioLogging.h" -#include "AvatarAudioStream.h" AvatarAudioStream::AvatarAudioStream(bool isStereo, int numStaticJitterFrames) : PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, numStaticJitterFrames) {} diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index d74c76032d..9b5c4d4f30 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarMixer.h" + #include #include #include @@ -31,8 +33,6 @@ #include #include -#include "AvatarMixer.h" - const QString AVATAR_MIXER_LOGGING_NAME = "avatar-mixer"; // FIXME - what we'd actually like to do is send to users at ~50% of their present rate down to 30hz. Assume 90 for now. diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index d5a8b37742..e185fe9167 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarMixerClientData.h" + #include #include #include -#include "AvatarMixerClientData.h" - AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID) : NodeData(nodeID) { diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 30d94ed772..984884adb2 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarMixerSlave.h" + #include #include @@ -28,10 +30,8 @@ #include #include - #include "AvatarMixer.h" #include "AvatarMixerClientData.h" -#include "AvatarMixerSlave.h" void AvatarMixerSlave::configure(ConstIter begin, ConstIter end) { _begin = begin; diff --git a/assignment-client/src/avatars/AvatarMixerSlave.h b/assignment-client/src/avatars/AvatarMixerSlave.h index bdddd5ceab..7be119c4b2 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.h +++ b/assignment-client/src/avatars/AvatarMixerSlave.h @@ -12,6 +12,8 @@ #ifndef hifi_AvatarMixerSlave_h #define hifi_AvatarMixerSlave_h +#include + class AvatarMixerClientData; class AvatarMixerSlaveStats { diff --git a/assignment-client/src/avatars/AvatarMixerSlavePool.cpp b/assignment-client/src/avatars/AvatarMixerSlavePool.cpp index 25b88686b7..962bba21d2 100644 --- a/assignment-client/src/avatars/AvatarMixerSlavePool.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlavePool.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarMixerSlavePool.h" + #include #include -#include "AvatarMixerSlavePool.h" - void AvatarMixerSlaveThread::run() { while (true) { wait(); diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 1f3f770867..e7210db83a 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ScriptableAvatar.h" + #include #include #include @@ -16,7 +18,6 @@ #include #include #include -#include "ScriptableAvatar.h" QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) { diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 70fad03d67..c108dad6cf 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -9,21 +9,23 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityServer.h" + #include #include +#include +#include + #include #include #include #include #include #include -#include -#include #include #include "AssignmentParentFinder.h" #include "EntityNodeData.h" -#include "EntityServer.h" #include "EntityServerConsts.h" #include "EntityTreeSendThread.h" diff --git a/assignment-client/src/messages/MessagesMixer.cpp b/assignment-client/src/messages/MessagesMixer.cpp index 4bf708cf34..c11c8f40a0 100644 --- a/assignment-client/src/messages/MessagesMixer.cpp +++ b/assignment-client/src/messages/MessagesMixer.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "MessagesMixer.h" + #include #include #include @@ -16,7 +18,6 @@ #include #include #include -#include "MessagesMixer.h" const QString MESSAGES_MIXER_LOGGING_NAME = "messages-mixer"; diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index bce6e7fe44..ef532bb33f 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeInboundPacketProcessor.h" + #include #include @@ -17,7 +19,6 @@ #include "OctreeServer.h" #include "OctreeServerConsts.h" -#include "OctreeInboundPacketProcessor.h" static QUuid DEFAULT_NODE_ID_REF; const quint64 TOO_LONG_SINCE_LAST_NACK = 1 * USECS_PER_SECOND; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 482b20272a..e9aa44b970 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeSendThread.h" + #include #include @@ -17,7 +19,6 @@ #include #include -#include "OctreeSendThread.h" #include "OctreeServer.h" #include "OctreeServerConsts.h" #include "OctreeLogging.h" diff --git a/domain-server/src/DomainServerNodeData.cpp b/domain-server/src/DomainServerNodeData.cpp index 974d4a59c3..486b51f9eb 100644 --- a/domain-server/src/DomainServerNodeData.cpp +++ b/domain-server/src/DomainServerNodeData.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainServerNodeData.h" + #include #include #include @@ -17,8 +19,6 @@ #include -#include "DomainServerNodeData.h" - DomainServerNodeData::StringPairHash DomainServerNodeData::_overrideHash; DomainServerNodeData::DomainServerNodeData() { diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index db41c77cf2..6b8e9a1718 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/domain-server/src/DomainServerWebSessionData.cpp b/domain-server/src/DomainServerWebSessionData.cpp index 3744af77f3..90eea17bec 100644 --- a/domain-server/src/DomainServerWebSessionData.cpp +++ b/domain-server/src/DomainServerWebSessionData.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainServerWebSessionData.h" + #include #include #include #include -#include "DomainServerWebSessionData.h" - DomainServerWebSessionData::DomainServerWebSessionData() : _username(), _roles() diff --git a/gvr-interface/src/Client.cpp b/gvr-interface/src/Client.cpp index 65238ad784..8f064c7fd5 100644 --- a/gvr-interface/src/Client.cpp +++ b/gvr-interface/src/Client.cpp @@ -9,14 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Client.h" + #include #include #include #include #include -#include "Client.h" - Client::Client(QObject* parent) : QObject(parent) { @@ -70,4 +70,4 @@ void Client::processDatagrams() { processVerifiedPacket(senderSockAddr, incomingPacket); } } -} \ No newline at end of file +} diff --git a/gvr-interface/src/GVRInterface.cpp b/gvr-interface/src/GVRInterface.cpp index 3d58396322..f9a29d4ac4 100644 --- a/gvr-interface/src/GVRInterface.cpp +++ b/gvr-interface/src/GVRInterface.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "GVRInterface.h" + #ifdef ANDROID #include @@ -32,8 +34,6 @@ #include "GVRMainWindow.h" #include "RenderingClient.h" -#include "GVRInterface.h" - static QString launchURLString = QString(); #ifdef ANDROID diff --git a/gvr-interface/src/GVRMainWindow.cpp b/gvr-interface/src/GVRMainWindow.cpp index 7a36aba66e..5495354233 100644 --- a/gvr-interface/src/GVRMainWindow.cpp +++ b/gvr-interface/src/GVRMainWindow.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "GVRMainWindow.h" + #include #include #include @@ -37,8 +39,6 @@ const float LIBOVR_LONG_PRESS_DURATION = 0.75f; #include "LoginDialog.h" #include "RenderingClient.h" -#include "GVRMainWindow.h" - GVRMainWindow::GVRMainWindow(QWidget* parent) : diff --git a/gvr-interface/src/LoginDialog.cpp b/gvr-interface/src/LoginDialog.cpp index 95b7451bcb..d4efd425bd 100644 --- a/gvr-interface/src/LoginDialog.cpp +++ b/gvr-interface/src/LoginDialog.cpp @@ -9,14 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LoginDialog.h" + #include #include #include #include #include -#include "LoginDialog.h" - LoginDialog::LoginDialog(QWidget* parent) : QDialog(parent) { @@ -66,4 +66,4 @@ void LoginDialog::setupGUI() { void LoginDialog::loginButtonClicked() { emit credentialsEntered(_usernameLineEdit->text(), _passwordLineEdit->text()); close(); -} \ No newline at end of file +} diff --git a/gvr-interface/src/RenderingClient.cpp b/gvr-interface/src/RenderingClient.cpp index f04be5cb7f..4c691a48e6 100644 --- a/gvr-interface/src/RenderingClient.cpp +++ b/gvr-interface/src/RenderingClient.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "RenderingClient.h" + #include #include @@ -17,8 +19,6 @@ #include #include -#include "RenderingClient.h" - RenderingClient* RenderingClient::_instance = NULL; RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString) : diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 7845158a80..8e15de673f 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarBookmarks.h" + #include #include #include @@ -27,7 +29,6 @@ #include "MainWindow.h" #include "Menu.h" -#include "AvatarBookmarks.h" #include "InterfaceLogging.h" #include "QVariantGLM.h" diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index f48b5e1f5b..6e99b81e50 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Bookmarks.h" + #include #include #include @@ -22,8 +24,6 @@ #include "Menu.h" #include "InterfaceLogging.h" -#include "Bookmarks.h" - Bookmarks::Bookmarks() : _isMenuSorted(false) { diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index b3c059de7f..684539145e 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -9,7 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DiscoverabilityManager.h" + #include +#include #include #include @@ -21,11 +24,8 @@ #include #include "Crashpad.h" -#include "DiscoverabilityManager.h" #include "Menu.h" -#include - const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::Connections; DiscoverabilityManager::DiscoverabilityManager() : diff --git a/interface/src/DiscoverabilityManager.h b/interface/src/DiscoverabilityManager.h index 96190b25d9..0c62ad5663 100644 --- a/interface/src/DiscoverabilityManager.h +++ b/interface/src/DiscoverabilityManager.h @@ -12,9 +12,13 @@ #ifndef hifi_DiscoverabilityManager_h #define hifi_DiscoverabilityManager_h +#include + #include #include +class QNetworkReply; + namespace Discoverability { enum Mode { None, diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index ec96f7c5d4..0d087c9b48 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// FIXME ordering of headers -#include "Application.h" #include "GLCanvas.h" +#include "Application.h" + bool GLCanvas::event(QEvent* event) { if (QEvent::Paint == event->type() && qApp->isAboutToQuit()) { return true; diff --git a/interface/src/InterfaceDynamicFactory.cpp b/interface/src/InterfaceDynamicFactory.cpp index b7861b56c8..e0d912b252 100644 --- a/interface/src/InterfaceDynamicFactory.cpp +++ b/interface/src/InterfaceDynamicFactory.cpp @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - +#include "InterfaceDynamicFactory.h" #include #include @@ -22,9 +22,6 @@ #include #include -#include "InterfaceDynamicFactory.h" - - EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) { switch (type) { case DYNAMIC_TYPE_NONE: diff --git a/interface/src/InterfaceParentFinder.cpp b/interface/src/InterfaceParentFinder.cpp index 14088bc716..b9be58f04b 100644 --- a/interface/src/InterfaceParentFinder.cpp +++ b/interface/src/InterfaceParentFinder.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "InterfaceParentFinder.h" + #include +#include +#include #include #include -#include -#include - -#include "InterfaceParentFinder.h" SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& success, SpatialParentTree* entityTree) const { SpatiallyNestableWeakPointer parent; diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index d7d73e962a..d06ba14bcf 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LODManager.h" + #include #include #include @@ -17,8 +19,6 @@ #include "ui/DialogsManager.h" #include "InterfaceLogging.h" -#include "LODManager.h" - Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index 285f533a7f..f29a8f18f9 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -9,10 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LocationBookmarks.h" + #include #include #include #include +#include #include #include @@ -21,9 +24,6 @@ #include "MainWindow.h" #include "Menu.h" -#include "LocationBookmarks.h" -#include - const QString LocationBookmarks::HOME_BOOKMARK = "Home"; LocationBookmarks::LocationBookmarks() { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 60d5abf260..bf0fc05350 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Menu.h" + #include #include #include @@ -52,8 +54,6 @@ #include "SpeechRecognizer.h" #endif -#include "Menu.h" - extern bool DEV_DECIMATE_TEXTURES; Menu* Menu::getInstance() { diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 0e34eebc80..3a5d92eb8c 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelPackager.h" + #include #include #include @@ -21,8 +23,6 @@ #include "ModelPropertiesDialog.h" #include "InterfaceLogging.h" -#include "ModelPackager.h" - static const int MAX_TEXTURE_SIZE = 1024; void copyDirectoryContent(QDir& from, QDir& to) { diff --git a/interface/src/ModelPackager.h b/interface/src/ModelPackager.h index 60b3825c4d..acd4d85f68 100644 --- a/interface/src/ModelPackager.h +++ b/interface/src/ModelPackager.h @@ -17,6 +17,8 @@ #include "ui/ModelsBrowser.h" +class FBXGeometry; + class ModelPackager : public QObject { public: static bool package(); diff --git a/interface/src/ModelPropertiesDialog.cpp b/interface/src/ModelPropertiesDialog.cpp index 35b07aa2b2..8984f89d07 100644 --- a/interface/src/ModelPropertiesDialog.cpp +++ b/interface/src/ModelPropertiesDialog.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelPropertiesDialog.h" + #include #include #include @@ -23,8 +25,6 @@ #include #include -#include "ModelPropertiesDialog.h" - ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping, const QString& basePath, const FBXGeometry& geometry) : diff --git a/interface/src/ModelSelector.cpp b/interface/src/ModelSelector.cpp index 2f85849fbe..7d91359a11 100644 --- a/interface/src/ModelSelector.cpp +++ b/interface/src/ModelSelector.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelSelector.h" + #include #include #include @@ -16,8 +18,6 @@ #include #include -#include "ModelSelector.h" - static const QString AVATAR_HEAD_AND_BODY_STRING = "Avatar Body with Head"; static const QString AVATAR_ATTACHEMENT_STRING = "Avatar Attachment"; static const QString ENTITY_MODEL_STRING = "Entity Model"; @@ -82,4 +82,4 @@ void ModelSelector::browse() { _browseButton->setText(fileInfo.fileName()); lastModelBrowseLocation.set(fileInfo.path()); } -} \ No newline at end of file +} diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index a4bf0bcefe..acde535d2b 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -9,13 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Application.h" #include "SecondaryCamera.h" -#include -#include -#include + #include +#include +#include +#include + +#include "Application.h" + using RenderArgsPointer = std::shared_ptr; void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { @@ -213,4 +216,4 @@ void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inp task.addJob("RenderDeferredTask", items); } task.addJob("EndSecondaryCamera", cachedArg); -} \ No newline at end of file +} diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index 026b72d865..3d9e52617c 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include class MainRenderTask { public: diff --git a/interface/src/SpeechRecognizer.cpp b/interface/src/SpeechRecognizer.cpp index f5d0cb9e24..4815d20a83 100644 --- a/interface/src/SpeechRecognizer.cpp +++ b/interface/src/SpeechRecognizer.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SpeechRecognizer.h" + #include #include #include "InterfaceLogging.h" -#include "SpeechRecognizer.h" #if defined(Q_OS_WIN) diff --git a/interface/src/SpeechRecognizer.mm b/interface/src/SpeechRecognizer.mm index 038bcce3e4..6b9da6f3e8 100644 --- a/interface/src/SpeechRecognizer.mm +++ b/interface/src/SpeechRecognizer.mm @@ -16,10 +16,10 @@ #import #import -#include - #include "SpeechRecognizer.h" +#include + @interface SpeechRecognizerDelegate : NSObject { SpeechRecognizer* _listener; } diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 7b50975c92..a27bd6c5db 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "UIUtil.h" + #include #include -#include "UIUtil.h" - int UIUtil::getWindowTitleBarHeight(const QWidget* window) { QStyleOptionTitleBar options; options.titleBarState = 1; diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp index 1a2e867d51..1750c00d37 100644 --- a/interface/src/audio/AudioScope.cpp +++ b/interface/src/audio/AudioScope.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioScope.h" + #include #include @@ -19,8 +21,6 @@ #include #include -#include "AudioScope.h" - static const unsigned int DEFAULT_FRAMES_PER_SCOPE = 5; static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20; static const unsigned int SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d24618fada..094b3bb67b 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarManager.h" + #include #include @@ -38,7 +40,6 @@ #include #include "Application.h" -#include "AvatarManager.h" #include "InterfaceLogging.h" #include "Menu.h" #include "MyAvatar.h" diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index fde8c49933..f791ea25bc 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -9,16 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Ledger.h" + #include #include #include #include -#include "Wallet.h" -#include "Ledger.h" -#include "CommerceLogging.h" + #include #include +#include "Wallet.h" +#include "CommerceLogging.h" + // inventory answers {status: 'success', data: {assets: [{id: "guid", title: "name", preview: "url"}....]}} // balance answers {status: 'success', data: {balance: integer}} // buy and receive_at answer {status: 'success'} diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 35e6ca1c92..982adb4b5e 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -9,22 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "CommerceLogging.h" -#include "Ledger.h" #include "Wallet.h" -#include "Application.h" -#include "ui/SecurityImageProvider.h" -#include "scripting/HMDScriptingInterface.h" -#include - -#include -#include -#include - -#include -#include -#include -#include #include #include @@ -33,7 +18,6 @@ #include #include #include - // I know, right? But per https://www.openssl.org/docs/faq.html // this avoids OPENSSL_Uplink(00007FF847238000,08): no OPENSSL_Applink // at runtime. @@ -41,6 +25,22 @@ #include #endif +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Application.h" +#include "CommerceLogging.h" +#include "Ledger.h" +#include "ui/SecurityImageProvider.h" +#include "scripting/HMDScriptingInterface.h" + static const char* KEY_FILE = "hifikey"; static const char* INSTRUCTIONS_FILE = "backup_instructions.html"; static const char* IMAGE_HEADER = "-----BEGIN SECURITY IMAGE-----\n"; diff --git a/interface/src/networking/CloseEventSender.cpp b/interface/src/networking/CloseEventSender.cpp index fe939afe05..16549d5510 100644 --- a/interface/src/networking/CloseEventSender.cpp +++ b/interface/src/networking/CloseEventSender.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "CloseEventSender.h" + #include #include #include @@ -22,8 +24,6 @@ #include #include -#include "CloseEventSender.h" - QNetworkRequest createNetworkRequest() { QNetworkRequest request; diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 0c2883a9a4..7d38e29710 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreePacketProcessor.h" + #include #include "Application.h" #include "Menu.h" -#include "OctreePacketProcessor.h" #include "SceneScriptingInterface.h" OctreePacketProcessor::OctreePacketProcessor() { diff --git a/interface/src/scripting/AccountServicesScriptingInterface.cpp b/interface/src/scripting/AccountServicesScriptingInterface.cpp index fc293098bb..3939fce91d 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.cpp +++ b/interface/src/scripting/AccountServicesScriptingInterface.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AccountServicesScriptingInterface.h" + #include "AccountManager.h" #include "Application.h" #include "DiscoverabilityManager.h" #include "ResourceCache.h" -#include "AccountServicesScriptingInterface.h" - AccountServicesScriptingInterface::AccountServicesScriptingInterface() { auto accountManager = DependencyManager::get(); connect(accountManager.data(), &AccountManager::usernameChanged, this, &AccountServicesScriptingInterface::onUsernameChanged); diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index 5774ee1da5..fb3c329def 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -18,6 +18,8 @@ #include #include #include + +#include #include class DownloadInfoResult { diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index a3c80bf1b6..f08a0bf382 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -9,18 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioDevices.h" + #include #include #include #include -#include "AudioDevices.h" - #include "Application.h" #include "AudioClient.h" #include "Audio.h" - #include "UserActivityLogger.h" using namespace scripting; diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 8ed5d59d07..fde2676986 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "GooglePolyScriptingInterface.h" + #include #include #include @@ -20,9 +22,7 @@ #include #include #include -#include -#include "GooglePolyScriptingInterface.h" #include "ScriptEngineLogging.h" const QString LIST_POLY_URL = "https://poly.googleapis.com/v1/assets?"; diff --git a/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp b/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp index ebb5ca9280..2692608106 100644 --- a/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp +++ b/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp @@ -9,13 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LimitlessVoiceRecognitionScriptingInterface.h" + #include #include -#include -#include -#include "LimitlessVoiceRecognitionScriptingInterface.h" +#include "InterfaceLogging.h" +#include "ui/AvatarInputs.h" const float LimitlessVoiceRecognitionScriptingInterface::_audioLevelThreshold = 0.33f; const int LimitlessVoiceRecognitionScriptingInterface::_voiceTimeoutDuration = 2000; diff --git a/interface/src/ui/DomainConnectionDialog.cpp b/interface/src/ui/DomainConnectionDialog.cpp index c0471dc5e1..57a8d41257 100644 --- a/interface/src/ui/DomainConnectionDialog.cpp +++ b/interface/src/ui/DomainConnectionDialog.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainConnectionDialog.h" + #include #include #include @@ -17,8 +19,6 @@ #include #include -#include "DomainConnectionDialog.h" - DomainConnectionDialog::DomainConnectionDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint) { diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 55c321723e..63794da60f 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HMDToolsDialog.h" + #include #include #include @@ -25,8 +27,7 @@ #include "Application.h" #include "MainWindow.h" #include "Menu.h" -#include "ui/DialogsManager.h" -#include "ui/HMDToolsDialog.h" +#include "DialogsManager.h" static const int WIDTH = 350; static const int HEIGHT = 100; diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index 34b68a123e..71e5293f30 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LodToolsDialog.h" + #include #include #include @@ -23,7 +25,6 @@ #include #include "Menu.h" -#include "ui/LodToolsDialog.h" LodToolsDialog::LodToolsDialog(QWidget* parent) : diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp index 44089119c6..4709cc0a9c 100644 --- a/interface/src/ui/ModelsBrowser.cpp +++ b/interface/src/ui/ModelsBrowser.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelsBrowser.h" + #include #include #include @@ -27,8 +29,6 @@ #include #include -#include "ModelsBrowser.h" - const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons", "attachments" }; static const QString S3_URL = "http://s3.amazonaws.com/hifi-public"; diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index ec5d800042..ea0f05f47f 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -9,20 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeStatsDialog.h" + #include #include #include - #include #include #include #include "Application.h" - #include "../octree/OctreePacketProcessor.h" -#include "ui/OctreeStatsDialog.h" OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* model) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint), diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 81bf5f251f..c05c8eadba 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -19,7 +19,6 @@ #include #define MAX_STATS 100 -#define DEFAULT_COLOR 0 class OctreeStatsDialog : public QDialog { Q_OBJECT @@ -42,7 +41,7 @@ protected: // Emits a 'closed' signal when this dialog is closed. void closeEvent(QCloseEvent*) override; - int AddStatItem(const char* caption, unsigned colorRGBA = DEFAULT_COLOR); + int AddStatItem(const char* caption, unsigned colorRGBA = 0); void RemoveStatItem(int item); void showAllOctreeServers(); diff --git a/interface/src/ui/OctreeStatsProvider.cpp b/interface/src/ui/OctreeStatsProvider.cpp index a393660c17..8917056be4 100644 --- a/interface/src/ui/OctreeStatsProvider.cpp +++ b/interface/src/ui/OctreeStatsProvider.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Application.h" +#include "OctreeStatsProvider.h" -#include "../octree/OctreePacketProcessor.h" -#include "ui/OctreeStatsProvider.h" +#include "Application.h" +#include "octree/OctreePacketProcessor.h" OctreeStatsProvider::OctreeStatsProvider(QObject* parent, NodeToOctreeSceneStats* model) : QObject(parent), diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index ed8fa53fe2..e7e3c91d13 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -8,13 +8,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OverlayConductor.h" + #include #include #include "Application.h" #include "avatar/AvatarManager.h" #include "InterfaceLogging.h" -#include "OverlayConductor.h" OverlayConductor::OverlayConductor() { diff --git a/interface/src/ui/OverlayConductor.h b/interface/src/ui/OverlayConductor.h index 1bdfe2ed79..cdd596a7bc 100644 --- a/interface/src/ui/OverlayConductor.h +++ b/interface/src/ui/OverlayConductor.h @@ -11,6 +11,8 @@ #ifndef hifi_OverlayConductor_h #define hifi_OverlayConductor_h +#include + class OverlayConductor { public: OverlayConductor(); @@ -34,12 +36,12 @@ private: bool _hmdMode { false }; // used by updateAvatarHasDriveInput - quint64 _desiredDrivingTimer { 0 }; + uint64_t _desiredDrivingTimer { 0 }; bool _desiredDriving { false }; bool _currentDriving { false }; // used by updateAvatarIsAtRest - quint64 _desiredAtRestTimer { 0 }; + uint64_t _desiredAtRestTimer { 0 }; bool _desiredAtRest { true }; bool _currentAtRest { true }; }; diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 69103a40b5..c6750ad424 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Snapshot.h" + #include #include #include @@ -31,7 +33,6 @@ #include #include "Application.h" -#include "Snapshot.h" #include "SnapshotUploader.h" // filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 62d3ed3db8..93aaed8aa4 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -16,6 +16,7 @@ #include #include +#include #include #include diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index 3c00be8358..7866e742d9 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SnapshotAnimated.h" + #include #include #include @@ -16,7 +18,6 @@ #include #include -#include "SnapshotAnimated.h" QTimer* SnapshotAnimated::snapshotAnimatedTimer = NULL; qint64 SnapshotAnimated::snapshotAnimatedTimestamp = 0; diff --git a/interface/src/ui/SnapshotUploader.cpp b/interface/src/ui/SnapshotUploader.cpp index 37505db629..67902c1a35 100644 --- a/interface/src/ui/SnapshotUploader.cpp +++ b/interface/src/ui/SnapshotUploader.cpp @@ -9,11 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SnapshotUploader.h" + #include #include + #include + #include "scripting/WindowScriptingInterface.h" -#include "SnapshotUploader.h" SnapshotUploader::SnapshotUploader(QUrl inWorldLocation, QString pathname) : _inWorldLocation(inWorldLocation), diff --git a/interface/src/ui/StandAloneJSConsole.cpp b/interface/src/ui/StandAloneJSConsole.cpp index 72b6ecc547..49cf22a9eb 100644 --- a/interface/src/ui/StandAloneJSConsole.cpp +++ b/interface/src/ui/StandAloneJSConsole.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "StandAloneJSConsole.h" + #include #include #include @@ -16,8 +18,6 @@ #include #include -#include "StandAloneJSConsole.h" - void StandAloneJSConsole::toggleConsole() { QMainWindow* mainWindow = qApp->getWindow(); if (!_jsConsole) { diff --git a/interface/src/ui/TestingDialog.cpp b/interface/src/ui/TestingDialog.cpp index 6f499f2a8d..6143f20ee6 100644 --- a/interface/src/ui/TestingDialog.cpp +++ b/interface/src/ui/TestingDialog.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ScriptEngines.h" +#include "TestingDialog.h" -#include "ui/TestingDialog.h" #include "Application.h" +#include "ScriptEngines.h" TestingDialog::TestingDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint), diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 7edc03490c..27e3bd0e2d 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelOverlay.h" + #include #include -#include "ModelOverlay.h" #include #include "Application.h" diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 2ead4558fe..7d358e85cc 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -8,8 +8,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GLMHelpers.h" #include "AnimClip.h" + +#include "GLMHelpers.h" #include "AnimationLogging.h" #include "AnimUtil.h" diff --git a/libraries/animation/src/AnimExpression.cpp b/libraries/animation/src/AnimExpression.cpp index 9777e9c6af..ddcbd01220 100644 --- a/libraries/animation/src/AnimExpression.cpp +++ b/libraries/animation/src/AnimExpression.cpp @@ -8,10 +8,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "AnimExpression.h" + #include -#include "AnimExpression.h" +#include + #include "AnimationLogging.h" AnimExpression::AnimExpression(const QString& str) : diff --git a/libraries/animation/src/AnimNode.cpp b/libraries/animation/src/AnimNode.cpp index 80093e43db..ba8e095109 100644 --- a/libraries/animation/src/AnimNode.cpp +++ b/libraries/animation/src/AnimNode.cpp @@ -8,9 +8,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "AnimNode.h" +#include + AnimNode::Pointer AnimNode::getParent() { return _parent.lock(); } diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 8173845205..4169ff61a7 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -8,6 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AnimNodeLoader.h" + #include #include #include @@ -19,7 +21,6 @@ #include "AnimBlendLinearMove.h" #include "AnimationLogging.h" #include "AnimOverlay.h" -#include "AnimNodeLoader.h" #include "AnimStateMachine.h" #include "AnimManipulator.h" #include "AnimInverseKinematics.h" diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 832ab8678c..483a7999c9 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -1,5 +1,5 @@ // -// AnimVariantMap.cpp +// AnimVariant.cpp // library/animation // // Created by Howard Stearns on 10/15/15. @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AnimVariant.h" // which has AnimVariant/AnimVariantMap + #include #include #include #include -#include "AnimVariant.h" // which has AnimVariant/AnimVariantMap const AnimVariant AnimVariant::False = AnimVariant(); diff --git a/libraries/animation/src/AnimationObject.cpp b/libraries/animation/src/AnimationObject.cpp index 25a5743121..7f0f35b104 100644 --- a/libraries/animation/src/AnimationObject.cpp +++ b/libraries/animation/src/AnimationObject.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AnimationObject.h" + #include #include "AnimationCache.h" -#include "AnimationObject.h" QStringList AnimationObject::getJointNames() const { return qscriptvalue_cast(thisObject())->getJointNames(); diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index f643719a2e..a5f79290cd 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioClient.h" + #include #include #include @@ -50,8 +52,6 @@ #include "AudioLogging.h" #include "AudioHelpers.h" -#include "AudioClient.h" - const int AudioClient::MIN_BUFFER_FRAMES = 1; const int AudioClient::MAX_BUFFER_FRAMES = 20; diff --git a/libraries/audio-client/src/AudioIOStats.cpp b/libraries/audio-client/src/AudioIOStats.cpp index 3bd3f4a47d..1717ad1f9c 100644 --- a/libraries/audio-client/src/AudioIOStats.cpp +++ b/libraries/audio-client/src/AudioIOStats.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioIOStats.h" + #include #include #include @@ -16,8 +18,6 @@ #include "AudioClient.h" -#include "AudioIOStats.h" - // This is called 1x/sec (see AudioClient) and we want it to log the last 5s static const int INPUT_READS_WINDOW = 5; static const int INPUT_UNPLAYED_WINDOW = 5; diff --git a/libraries/audio/src/AudioFOA.cpp b/libraries/audio/src/AudioFOA.cpp index 718b29d1b2..16c0721047 100644 --- a/libraries/audio/src/AudioFOA.cpp +++ b/libraries/audio/src/AudioFOA.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioFOA.h" + #include #include -#include "AudioFOA.h" #include "AudioFOAData.h" #if defined(_MSC_VER) diff --git a/libraries/audio/src/AudioGate.cpp b/libraries/audio/src/AudioGate.cpp index 5ef5ee25b5..e9cdf832d2 100644 --- a/libraries/audio/src/AudioGate.cpp +++ b/libraries/audio/src/AudioGate.cpp @@ -6,12 +6,13 @@ // Copyright 2017 High Fidelity, Inc. // +#include "AudioGate.h" + #include #include #include #include "AudioDynamics.h" -#include "AudioGate.h" // log2 domain headroom bits above 0dB (int32_t) static const int LOG2_HEADROOM_Q30 = 1; diff --git a/libraries/audio/src/AudioHRTF.cpp b/libraries/audio/src/AudioHRTF.cpp index aa951210a6..c0751c6a20 100644 --- a/libraries/audio/src/AudioHRTF.cpp +++ b/libraries/audio/src/AudioHRTF.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioHRTF.h" + #include #include #include -#include "AudioHRTF.h" #include "AudioHRTFData.h" #if defined(_MSC_VER) diff --git a/libraries/audio/src/AudioLimiter.cpp b/libraries/audio/src/AudioLimiter.cpp index e20a070bd6..79bb84f7b1 100644 --- a/libraries/audio/src/AudioLimiter.cpp +++ b/libraries/audio/src/AudioLimiter.cpp @@ -6,10 +6,11 @@ // Copyright 2016 High Fidelity, Inc. // +#include "AudioLimiter.h" + #include #include "AudioDynamics.h" -#include "AudioLimiter.h" // // Limiter (common) diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp index d457ce7a96..a7c6fefd39 100644 --- a/libraries/audio/src/AudioReverb.cpp +++ b/libraries/audio/src/AudioReverb.cpp @@ -6,12 +6,12 @@ // Copyright 2015 High Fidelity, Inc. // +#include "AudioReverb.h" + #include #include #include -#include "AudioReverb.h" - #ifdef _MSC_VER #include #define MULHI(a,b) ((int32_t)(__emul(a, b) >> 32)) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 518fdd3c17..d8531ec216 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioRingBuffer.h" + #include #include #include @@ -21,8 +23,6 @@ #include "AudioLogging.h" -#include "AudioRingBuffer.h" - static const QString RING_BUFFER_OVERFLOW_DEBUG { "AudioRingBuffer::writeData has overflown the buffer. Overwriting old data." }; static const QString DROPPED_SILENT_DEBUG { "AudioRingBuffer::addSilentSamples dropping silent samples to prevent overflow." }; diff --git a/libraries/audio/src/AudioSRC.cpp b/libraries/audio/src/AudioSRC.cpp index fbdf890246..d488eccb6a 100644 --- a/libraries/audio/src/AudioSRC.cpp +++ b/libraries/audio/src/AudioSRC.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioSRC.h" + #include #include #include -#include "AudioSRC.h" #include "AudioSRCData.h" #ifndef MAX diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index d60c5ba4ab..7645a674e4 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -9,13 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "InboundAudioStream.h" + #include #include #include #include -#include "InboundAudioStream.h" #include "AudioLogging.h" const bool InboundAudioStream::DEFAULT_DYNAMIC_JITTER_BUFFER_ENABLED = true; diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index a06dba5389..2f357416f2 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "InjectedAudioStream.h" + #include #include @@ -17,7 +19,6 @@ #include #include -#include "InjectedAudioStream.h" #include "AudioHelpers.h" InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, bool isStereo, int numStaticJitterFrames) : diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 672c0b69b3..cd93f7b52e 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Sound.h" + #include #include @@ -29,8 +31,6 @@ #include "AudioLogging.h" #include "AudioSRC.h" -#include "Sound.h" - QScriptValue soundSharedPointerToScriptValue(QScriptEngine* engine, const SharedSoundPointer& in) { return engine->newQObject(new SoundScriptingInterface(in), QScriptEngine::ScriptOwnership); } diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index b564ad6a3b..829c98a418 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AvatarHashMap.h" + #include #include @@ -17,7 +19,6 @@ #include #include "AvatarLogging.h" -#include "AvatarHashMap.h" AvatarHashMap::AvatarHashMap() { auto nodeList = DependencyManager::get(); diff --git a/libraries/baking/src/Baker.cpp b/libraries/baking/src/Baker.cpp index 2adedf08a1..78a34ac5e8 100644 --- a/libraries/baking/src/Baker.cpp +++ b/libraries/baking/src/Baker.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ModelBakingLoggingCategory.h" - #include "Baker.h" +#include "ModelBakingLoggingCategory.h" + bool Baker::shouldStop() { if (_shouldAbort) { setWasAborted(true); diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index c8ba98f0b1..e3839bb95a 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "FBXBaker.h" + #include // need this include so we don't get an error looking for std::isnan #include @@ -31,8 +33,6 @@ #include "ModelBakingLoggingCategory.h" #include "TextureBaker.h" -#include "FBXBaker.h" - void FBXBaker::bake() { qDebug() << "FBXBaker" << _modelURL << "bake starting"; diff --git a/libraries/baking/src/JSBaker.cpp b/libraries/baking/src/JSBaker.cpp index 9932ad633e..b19336f4ca 100644 --- a/libraries/baking/src/JSBaker.cpp +++ b/libraries/baking/src/JSBaker.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "JSBaker.h" + #include -#include "JSBaker.h" #include "Baker.h" const int ASCII_CHARACTERS_UPPER_LIMIT = 126; diff --git a/libraries/baking/src/JSBaker.h b/libraries/baking/src/JSBaker.h index b5889440cb..a7c3e62174 100644 --- a/libraries/baking/src/JSBaker.h +++ b/libraries/baking/src/JSBaker.h @@ -12,6 +12,8 @@ #ifndef hifi_JSBaker_h #define hifi_JSBaker_h +#include + #include "Baker.h" #include "JSBakingLoggingCategory.h" diff --git a/libraries/baking/src/OBJBaker.cpp b/libraries/baking/src/OBJBaker.cpp index 1fe53f26eb..cf62bc4fa8 100644 --- a/libraries/baking/src/OBJBaker.cpp +++ b/libraries/baking/src/OBJBaker.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OBJBaker.h" + #include #include -#include "OBJBaker.h" #include "OBJReader.h" #include "FBXWriter.h" diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index 45895494a0..b6957a2712 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TextureBaker.h" + #include #include #include @@ -22,8 +24,6 @@ #include "ModelBakingLoggingCategory.h" -#include "TextureBaker.h" - const QString BAKED_TEXTURE_KTX_EXT = ".ktx"; const QString BAKED_TEXTURE_BCN_SUFFIX = "_bcn.ktx"; const QString BAKED_META_TEXTURE_SUFFIX = ".texmeta.json"; diff --git a/libraries/baking/src/TextureBaker.h b/libraries/baking/src/TextureBaker.h index 93b01080cd..54839c001a 100644 --- a/libraries/baking/src/TextureBaker.h +++ b/libraries/baking/src/TextureBaker.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/libraries/controllers/src/controllers/DeviceProxy.cpp b/libraries/controllers/src/controllers/DeviceProxy.cpp deleted file mode 100644 index f03354c52d..0000000000 --- a/libraries/controllers/src/controllers/DeviceProxy.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/10/18 -// (based on UserInputMapper inner class created by Sam Gateau on 4/27/15) -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "DeviceProxy.h" - diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp index 6f0296c09d..967838ef84 100644 --- a/libraries/controllers/src/controllers/Pose.cpp +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -6,13 +6,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Pose.h" + #include #include #include -#include "Pose.h" - namespace controller { Pose::Pose(const vec3& translation, const quat& rotation, diff --git a/libraries/controllers/src/controllers/impl/Mapping.cpp b/libraries/controllers/src/controllers/impl/Mapping.cpp deleted file mode 100644 index dd8e1c1d48..0000000000 --- a/libraries/controllers/src/controllers/impl/Mapping.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "Mapping.h" diff --git a/libraries/controllers/src/controllers/impl/Route.cpp b/libraries/controllers/src/controllers/impl/Route.cpp deleted file mode 100644 index c74f809195..0000000000 --- a/libraries/controllers/src/controllers/impl/Route.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "Route.h" diff --git a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp deleted file mode 100644 index f833eedb60..0000000000 --- a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/23 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "EndpointConditional.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp deleted file mode 100644 index 5dea1de34e..0000000000 --- a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/23 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "ArrayEndpoint.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp deleted file mode 100644 index 89bbe5d777..0000000000 --- a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/23 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "StandardEndpoint.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.cpp b/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.cpp deleted file mode 100644 index 8bd3d2db89..0000000000 --- a/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/25 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "ConstrainToIntegerFilter.h" diff --git a/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.cpp b/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.cpp deleted file mode 100644 index f1abc8cecd..0000000000 --- a/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/25 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "ConstrainToPositiveIntegerFilter.h" diff --git a/libraries/controllers/src/controllers/impl/filters/InvertFilter.cpp b/libraries/controllers/src/controllers/impl/filters/InvertFilter.cpp deleted file mode 100644 index 5407c6dd1d..0000000000 --- a/libraries/controllers/src/controllers/impl/filters/InvertFilter.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/25 -// Copyright 2015 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 -// - -// NOTE: we don't need to include this header unless/until we add additional symbols. -// By removing this header we prevent these warnings on windows: -// -// warning LNK4221: This object file does not define any previously undefined public symbols, -// so it will not be used by any link operation that consumes this library -// -//#include "InvertFilter.h" diff --git a/libraries/embedded-webserver/src/HTTPConnection.cpp b/libraries/embedded-webserver/src/HTTPConnection.cpp index 280b44cec0..12da599575 100644 --- a/libraries/embedded-webserver/src/HTTPConnection.cpp +++ b/libraries/embedded-webserver/src/HTTPConnection.cpp @@ -9,15 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HTTPConnection.h" #include #include #include +#include -#include "HTTPConnection.h" #include "EmbeddedWebserverLogging.h" #include "HTTPManager.h" -#include const char* HTTPConnection::StatusCode200 = "200 OK"; const char* HTTPConnection::StatusCode301 = "301 Moved Permanently"; diff --git a/libraries/embedded-webserver/src/HTTPManager.cpp b/libraries/embedded-webserver/src/HTTPManager.cpp index bd1b545412..db6fc8e084 100644 --- a/libraries/embedded-webserver/src/HTTPManager.cpp +++ b/libraries/embedded-webserver/src/HTTPManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HTTPManager.h" + #include #include #include @@ -18,7 +20,6 @@ #include "HTTPConnection.h" #include "EmbeddedWebserverLogging.h" -#include "HTTPManager.h" const int SOCKET_ERROR_EXIT_CODE = 2; const int SOCKET_CHECK_INTERVAL_IN_MS = 30000; diff --git a/libraries/embedded-webserver/src/HTTPSConnection.cpp b/libraries/embedded-webserver/src/HTTPSConnection.cpp index 7af14ce0a7..f5473d577f 100644 --- a/libraries/embedded-webserver/src/HTTPSConnection.cpp +++ b/libraries/embedded-webserver/src/HTTPSConnection.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "EmbeddedWebserverLogging.h" #include "HTTPSConnection.h" +#include "EmbeddedWebserverLogging.h" + HTTPSConnection::HTTPSConnection(QSslSocket* sslSocket, HTTPSManager* parentManager) : HTTPConnection(sslSocket, parentManager) { diff --git a/libraries/embedded-webserver/src/HTTPSManager.cpp b/libraries/embedded-webserver/src/HTTPSManager.cpp index ee61f15457..8ba44f98ac 100644 --- a/libraries/embedded-webserver/src/HTTPSManager.cpp +++ b/libraries/embedded-webserver/src/HTTPSManager.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HTTPSManager.h" + #include #include "HTTPSConnection.h" -#include "HTTPSManager.h" - HTTPSManager::HTTPSManager(QHostAddress listenAddress, quint16 port, const QSslCertificate& certificate, const QSslKey& privateKey, const QString& documentRoot, HTTPSRequestHandler* requestHandler, QObject* parent) : HTTPManager(listenAddress, port, documentRoot, requestHandler, parent), diff --git a/libraries/entities/src/DeleteEntityOperator.cpp b/libraries/entities/src/DeleteEntityOperator.cpp index 347d40ea49..d369e08ecf 100644 --- a/libraries/entities/src/DeleteEntityOperator.cpp +++ b/libraries/entities/src/DeleteEntityOperator.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DeleteEntityOperator.h" + #include "EntityItem.h" #include "EntityTree.h" #include "EntityTreeElement.h" - #include "EntitiesLogging.h" -#include "DeleteEntityOperator.h" DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree, const EntityItemID& searchEntityID) : _tree(tree), diff --git a/libraries/entities/src/DeleteEntityOperator.h b/libraries/entities/src/DeleteEntityOperator.h index 135949a53d..3b3ee2a868 100644 --- a/libraries/entities/src/DeleteEntityOperator.h +++ b/libraries/entities/src/DeleteEntityOperator.h @@ -12,6 +12,12 @@ #ifndef hifi_DeleteEntityOperator_h #define hifi_DeleteEntityOperator_h +#include + +#include + +#include "EntityItem.h" + class EntityToDeleteDetails { public: EntityItemPointer entity; diff --git a/libraries/entities/src/EntityDynamicInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp index d43bdd7b51..1115559342 100644 --- a/libraries/entities/src/EntityDynamicInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -89,10 +89,9 @@ variables. These argument variables are used by the code which is run when bull */ -#include "EntityItem.h" - #include "EntityDynamicInterface.h" +#include "EntityItem.h" /**jsdoc *

    An entity action may be one of the following types:

    diff --git a/libraries/entities/src/EntityDynamicInterface.h b/libraries/entities/src/EntityDynamicInterface.h index 40e39eecf1..6b82e7df73 100644 --- a/libraries/entities/src/EntityDynamicInterface.h +++ b/libraries/entities/src/EntityDynamicInterface.h @@ -13,9 +13,12 @@ #define hifi_EntityDynamicInterface_h #include -#include + #include +#include +#include + class EntityItem; class EntityItemID; class EntitySimulation; diff --git a/libraries/entities/src/EntityEditFilters.cpp b/libraries/entities/src/EntityEditFilters.cpp index 676b1ce518..94df7eb465 100644 --- a/libraries/entities/src/EntityEditFilters.cpp +++ b/libraries/entities/src/EntityEditFilters.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityEditFilters.h" #include #include -#include "EntityEditFilters.h" QList EntityEditFilters::getZonesByPosition(glm::vec3& position) { QList zones; diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 5d7bd61854..d89dd4f9d0 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -9,16 +9,20 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityEditPacketSender.h" + #include + #include + +#include #include #include #include -#include "EntityEditPacketSender.h" + #include "EntitiesLogging.h" #include "EntityItem.h" #include "EntityItemProperties.h" -#include EntityEditPacketSender::EntityEditPacketSender() { auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4638b46437..4d7c114176 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -9,24 +9,28 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include -#include +#include "EntityItemProperties.h" + #include #include #include #include -#include + +#include +#include +#include +#include #include #include + +#include #include #include #include #include + #include "EntitiesLogging.h" #include "EntityItem.h" -#include "EntityItemProperties.h" #include "ModelEntityItem.h" #include "PolyLineEntityItem.h" diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 38e4f0c8c0..39ea2e0bdd 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "AnimationPropertyGroup.h" #include "EntityItemID.h" diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index d95dbf2990..ee9fb10554 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -18,15 +18,13 @@ #include #include -class EntityTree; -using EntityTreePointer = std::shared_ptr; - #include "AddEntityOperator.h" #include "EntityTreeElement.h" #include "DeleteEntityOperator.h" #include "MovingEntitiesOperator.h" -class EntityEditFilters; +class EntityTree; +using EntityTreePointer = std::shared_ptr; class EntitySimulation; diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 694542b04e..9611063f8b 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityTypes.h" + #include #include @@ -16,7 +18,6 @@ #include "EntityItem.h" #include "EntityItemProperties.h" -#include "EntityTypes.h" #include "EntitiesLogging.h" #include "LightEntityItem.h" diff --git a/libraries/entities/src/HazePropertyGroup.cpp b/libraries/entities/src/HazePropertyGroup.cpp index f137fca5ce..c15b28707c 100644 --- a/libraries/entities/src/HazePropertyGroup.cpp +++ b/libraries/entities/src/HazePropertyGroup.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HazePropertyGroup.h" + #include -#include "HazePropertyGroup.h" #include "EntityItemProperties.h" #include "EntityItemPropertiesMacros.h" diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index f0fbb20f98..e95af7ebf9 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "LightEntityItem.h" #include @@ -19,7 +20,6 @@ #include "EntityItemProperties.h" #include "EntityTree.h" #include "EntityTreeElement.h" -#include "LightEntityItem.h" const bool LightEntityItem::DEFAULT_IS_SPOTLIGHT = false; const float LightEntityItem::DEFAULT_INTENSITY = 1.0f; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 0f59bc673d..cf89a73214 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -9,18 +9,20 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelEntityItem.h" + #include +#include + #include #include -#include #include "EntitiesLogging.h" #include "EntityItemProperties.h" #include "EntityTree.h" #include "EntityTreeElement.h" #include "ResourceCache.h" -#include "ModelEntityItem.h" const QString ModelEntityItem::DEFAULT_MODEL_URL = QString(""); const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString(""); diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index cf043dd93e..4b908745e0 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "MovingEntitiesOperator.h" + #include "EntityItem.h" #include "EntityTree.h" #include "EntityTreeElement.h" #include "EntitiesLogging.h" -#include "MovingEntitiesOperator.h" - MovingEntitiesOperator::MovingEntitiesOperator() { } MovingEntitiesOperator::~MovingEntitiesOperator() { diff --git a/libraries/entities/src/MovingEntitiesOperator.h b/libraries/entities/src/MovingEntitiesOperator.h index d93efa60f2..9e98374fc3 100644 --- a/libraries/entities/src/MovingEntitiesOperator.h +++ b/libraries/entities/src/MovingEntitiesOperator.h @@ -14,8 +14,7 @@ #include -#include "EntityTypes.h" -#include "EntityTreeElement.h" +#include "EntityItem.h" class EntityToMoveDetails { public: diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index d9ef5e2178..d1fc3d2775 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -26,6 +26,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ParticleEffectEntityItem.h" #include #include @@ -38,8 +39,6 @@ #include "EntityTreeElement.h" #include "EntitiesLogging.h" #include "EntityScriptingInterface.h" -#include "ParticleEffectEntityItem.h" - using namespace particle; diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 420c570e8d..5b3167b9ba 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "PolyLineEntityItem.h" #include @@ -19,7 +20,6 @@ #include "EntityTree.h" #include "EntityTreeElement.h" #include "OctreeConstants.h" -#include "PolyLineEntityItem.h" const float PolyLineEntityItem::DEFAULT_LINE_WIDTH = 0.1f; const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 60; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 520d892682..943ae2e462 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -6,6 +6,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ShapeEntityItem.h" #include @@ -17,7 +18,6 @@ #include "EntityItemProperties.h" #include "EntityTree.h" #include "EntityTreeElement.h" -#include "ShapeEntityItem.h" namespace entity { diff --git a/libraries/entities/src/SkyboxPropertyGroup.cpp b/libraries/entities/src/SkyboxPropertyGroup.cpp index f8baf57856..ba40c3fa6f 100644 --- a/libraries/entities/src/SkyboxPropertyGroup.cpp +++ b/libraries/entities/src/SkyboxPropertyGroup.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SkyboxPropertyGroup.h" + #include -#include "SkyboxPropertyGroup.h" #include "EntityItemProperties.h" #include "EntityItemPropertiesMacros.h" diff --git a/libraries/entities/src/SkyboxPropertyGroup.h b/libraries/entities/src/SkyboxPropertyGroup.h index d7b422bf11..a94365d24d 100644 --- a/libraries/entities/src/SkyboxPropertyGroup.h +++ b/libraries/entities/src/SkyboxPropertyGroup.h @@ -18,6 +18,8 @@ #include +#include + #include "PropertyGroup.h" #include "EntityItemPropertiesMacros.h" diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 97080d3ca2..56e12e66d9 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TextEntityItem.h" #include @@ -21,7 +22,6 @@ #include "EntitiesLogging.h" #include "EntityTree.h" #include "EntityTreeElement.h" -#include "TextEntityItem.h" const QString TextEntityItem::DEFAULT_TEXT(""); const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f; diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index b07d0597bc..3a6095b89f 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ZoneEntityItem.h" #include @@ -18,7 +19,6 @@ #include "EntityItemProperties.h" #include "EntityTree.h" #include "EntityTreeElement.h" -#include "ZoneEntityItem.h" #include "EntityEditFilters.h" bool ZoneEntityItem::_zonesArePickable = false; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 86422ef70c..81637e82a8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "FBXReader.h" + #include #include #include @@ -31,7 +33,6 @@ #include #include -#include "FBXReader.h" #include "ModelFormatLogging.h" // TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index d63a5b3cc4..75596862d2 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "FSTReader.h" + #include #include #include @@ -17,8 +19,6 @@ #include #include -#include "FSTReader.h" - QVariantHash FSTReader::parseMapping(QIODevice* device) { QVariantHash properties; diff --git a/libraries/fbx/src/GLTFReader.cpp b/libraries/fbx/src/GLTFReader.cpp index 0c04b3d733..f322c2319e 100644 --- a/libraries/fbx/src/GLTFReader.cpp +++ b/libraries/fbx/src/GLTFReader.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "GLTFReader.h" + #include #include #include @@ -28,7 +30,6 @@ #include #include -#include "GLTFReader.h" #include "FBXReader.h" @@ -1377,4 +1378,4 @@ void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) { } qCDebug(modelformat) << "\n"; -} \ No newline at end of file +} diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp index 8e6d4bec9b..585a719638 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp @@ -5,22 +5,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Forward.h" - #include "ScriptableMesh.h" -#include "ScriptableMeshPart.h" -#include "GraphicsScriptingUtil.h" -#include "OBJWriter.h" -#include #include -#include + #include #include #include + +#include #include #include #include +#include + +#include "Forward.h" +#include "ScriptableMeshPart.h" +#include "GraphicsScriptingUtil.h" +#include "OBJWriter.h" // #define SCRIPTABLE_MESH_DEBUG 1 diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.cpp index 4414b0ad7e..192071d3af 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.cpp @@ -5,22 +5,23 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Forward.h" - #include "ScriptableMeshPart.h" -#include "GraphicsScriptingUtil.h" -#include "OBJWriter.h" -#include -#include -#include #include #include #include + +#include +#include +#include #include #include #include +#include "Forward.h" +#include "GraphicsScriptingUtil.h" +#include "OBJWriter.h" + QString scriptable::ScriptableMeshPart::toOBJ() { if (!getMeshPointer()) { diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index c65764a225..7aaa182163 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -8,14 +8,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GraphicsScriptingUtil.h" #include "ScriptableModel.h" -#include "ScriptableMesh.h" #include +#include "GraphicsScriptingUtil.h" +#include "ScriptableMesh.h" #include "graphics/Material.h" - #include "image/Image.h" // #define SCRIPTABLE_MESH_DEBUG 1 diff --git a/libraries/graphics/src/graphics/Haze.cpp b/libraries/graphics/src/graphics/Haze.cpp index dfe70175f4..d5a060b90b 100644 --- a/libraries/graphics/src/graphics/Haze.cpp +++ b/libraries/graphics/src/graphics/Haze.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "Haze.h" +#include + using namespace graphics; const float Haze::INITIAL_HAZE_RANGE{ 1000.0f }; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index edb2992128..dd6a7fffe9 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AddressManager.h" + #include #include #include @@ -23,7 +25,6 @@ #include #include -#include "AddressManager.h" #include "NodeList.h" #include "NetworkLogging.h" #include "UserActivityLogger.h" diff --git a/libraries/networking/src/Assignment.cpp b/libraries/networking/src/Assignment.cpp index 58a4446aa6..71a3cfb269 100644 --- a/libraries/networking/src/Assignment.cpp +++ b/libraries/networking/src/Assignment.cpp @@ -9,17 +9,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "udt/PacketHeaders.h" -#include "SharedUtil.h" -#include "UUID.h" +#include "Assignment.h" #include #include -#include "Assignment.h" #include #include +#include "udt/PacketHeaders.h" +#include "SharedUtil.h" +#include "UUID.h" + Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) { switch (nodeType) { case NodeType::AudioMixer: diff --git a/libraries/networking/src/AtpReply.cpp b/libraries/networking/src/AtpReply.cpp index 6417478005..b2b7e8bee7 100644 --- a/libraries/networking/src/AtpReply.cpp +++ b/libraries/networking/src/AtpReply.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ResourceManager.h" #include "AtpReply.h" +#include "ResourceManager.h" + AtpReply::AtpReply(const QUrl& url, QObject* parent) : _resourceRequest(DependencyManager::get()->createResourceRequest(parent, url)) { setOperation(QNetworkAccessManager::GetOperation); diff --git a/libraries/networking/src/BandwidthRecorder.cpp b/libraries/networking/src/BandwidthRecorder.cpp index d43d4cf21f..5ad3494017 100644 --- a/libraries/networking/src/BandwidthRecorder.cpp +++ b/libraries/networking/src/BandwidthRecorder.cpp @@ -11,9 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "BandwidthRecorder.h" +#include BandwidthRecorder::Channel::Channel() { } diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 51f93d13b0..8756a0cc4b 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DataServerAccountInfo.h" + #include #include @@ -20,7 +22,6 @@ #include #include "NetworkLogging.h" -#include "DataServerAccountInfo.h" #ifdef __clang__ #pragma clang diagnostic ignored "-Wdeprecated-declarations" diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index e2a3e79c79..a1bfcdd275 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HifiSockAddr.h" + #include #include #include -#include "HifiSockAddr.h" #include "NetworkLogging.h" int hifiSockAddrMetaTypeId = qRegisterMetaType(); diff --git a/libraries/networking/src/LocationScriptingInterface.cpp b/libraries/networking/src/LocationScriptingInterface.cpp index aae1da73ba..39845558a8 100644 --- a/libraries/networking/src/LocationScriptingInterface.cpp +++ b/libraries/networking/src/LocationScriptingInterface.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AddressManager.h" - #include "LocationScriptingInterface.h" +#include "AddressManager.h" + LocationScriptingInterface* LocationScriptingInterface::getInstance() { static LocationScriptingInterface sharedInstance; return &sharedInstance; diff --git a/libraries/networking/src/NetworkAccessManager.cpp b/libraries/networking/src/NetworkAccessManager.cpp index fd356c3e94..f73243e675 100644 --- a/libraries/networking/src/NetworkAccessManager.cpp +++ b/libraries/networking/src/NetworkAccessManager.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "NetworkAccessManager.h" + #include #include "AtpReply.h" -#include "NetworkAccessManager.h" #include QThreadStorage networkAccessManagers; diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 73b7c44e7e..626503d8ae 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Node.h" + #include #include @@ -21,8 +23,6 @@ #include "NodePermissions.h" #include "SharedUtil.h" -#include "Node.h" - const QString UNKNOWN_NodeType_t_NAME = "Unknown"; int NodePtrMetaTypeId = qRegisterMetaType("Node*"); diff --git a/libraries/networking/src/OAuthAccessToken.cpp b/libraries/networking/src/OAuthAccessToken.cpp index 0c14e5e074..44db2a799e 100644 --- a/libraries/networking/src/OAuthAccessToken.cpp +++ b/libraries/networking/src/OAuthAccessToken.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "OAuthAccessToken.h" +#include + OAuthAccessToken::OAuthAccessToken() : token(), refreshToken(), diff --git a/libraries/networking/src/OAuthNetworkAccessManager.cpp b/libraries/networking/src/OAuthNetworkAccessManager.cpp index a30786efa4..272ff47a49 100644 --- a/libraries/networking/src/OAuthNetworkAccessManager.cpp +++ b/libraries/networking/src/OAuthNetworkAccessManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OAuthNetworkAccessManager.h" + #include #include #include @@ -18,8 +20,6 @@ #include "NetworkingConstants.h" #include "SharedUtil.h" -#include "OAuthNetworkAccessManager.h" - QThreadStorage oauthNetworkAccessManagers; OAuthNetworkAccessManager* OAuthNetworkAccessManager::getInstance() { diff --git a/libraries/networking/src/PacketSender.cpp b/libraries/networking/src/PacketSender.cpp index 02c4815f1f..6288743c46 100644 --- a/libraries/networking/src/PacketSender.cpp +++ b/libraries/networking/src/PacketSender.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "PacketSender.h" + #include #include #include #include "NodeList.h" -#include "PacketSender.h" #include "SharedUtil.h" const quint64 PacketSender::USECS_PER_SECOND = 1000 * 1000; diff --git a/libraries/networking/src/RSAKeypairGenerator.cpp b/libraries/networking/src/RSAKeypairGenerator.cpp index a98cf74564..8ca8b81ea3 100644 --- a/libraries/networking/src/RSAKeypairGenerator.cpp +++ b/libraries/networking/src/RSAKeypairGenerator.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "RSAKeypairGenerator.h" + #include #include #include @@ -16,8 +18,6 @@ #include #include "NetworkLogging.h" - -#include "RSAKeypairGenerator.h" #ifdef __clang__ #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index c18d4ed1e8..7145744206 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ReceivedPacketProcessor.h" + #include #include "NodeList.h" -#include "ReceivedPacketProcessor.h" #include "SharedUtil.h" ReceivedPacketProcessor::ReceivedPacketProcessor() { diff --git a/libraries/networking/src/ReceivedPacketProcessor.h b/libraries/networking/src/ReceivedPacketProcessor.h index f71abce1f1..6c590ec54d 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.h +++ b/libraries/networking/src/ReceivedPacketProcessor.h @@ -14,8 +14,12 @@ #include +#include "NodeList.h" + #include "GenericThread.h" +class ReceivedMessage; + /// Generalized threaded processor for handling received inbound packets. class ReceivedPacketProcessor : public GenericThread { Q_OBJECT diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 8b6de7da11..9a69d9b3d8 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ThreadedAssignment.h" + #include #include #include @@ -17,8 +19,6 @@ #include -#include "ThreadedAssignment.h" - #include "NetworkLogging.h" ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) : diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index 0cfd1e09e7..7a92d4bad9 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -9,16 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "UserActivityLogger.h" + #include #include #include #include -#include "NetworkLogging.h" - -#include "UserActivityLogger.h" #include + #include "AddressManager.h" +#include "NetworkLogging.h" UserActivityLogger::UserActivityLogger() { _timer.start(); diff --git a/libraries/networking/src/WalletTransaction.cpp b/libraries/networking/src/WalletTransaction.cpp index 0c823555fd..2bb66c67d0 100644 --- a/libraries/networking/src/WalletTransaction.cpp +++ b/libraries/networking/src/WalletTransaction.cpp @@ -9,13 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "WalletTransaction.h" + #include #include -#include "WalletTransaction.h" - - WalletTransaction::WalletTransaction() : _uuid(), _destinationUUID(), diff --git a/libraries/networking/src/udt/ConnectionStats.cpp b/libraries/networking/src/udt/ConnectionStats.cpp index 46d88e680f..986da062f2 100644 --- a/libraries/networking/src/udt/ConnectionStats.cpp +++ b/libraries/networking/src/udt/ConnectionStats.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "ConnectionStats.h" +#include + using namespace udt; using namespace std::chrono; diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 2efd32f2e8..5f943fabf2 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Octree.h" + #include #include #include @@ -43,7 +45,6 @@ #include #include -#include "Octree.h" #include "OctreeConstants.h" #include "OctreeLogging.h" #include "OctreeQueryNode.h" diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 4f10c9bf79..0156013821 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeEditPacketSender.h" + #include #include @@ -16,7 +18,6 @@ #include #include #include "OctreeLogging.h" -#include "OctreeEditPacketSender.h" const int OctreeEditPacketSender::DEFAULT_MAX_PENDING_MESSAGES = PacketSender::DEFAULT_PACKETS_PER_SECOND; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index a666ba0426..b94d0d57e1 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeElement.h" + #include #include #include @@ -21,17 +23,16 @@ #include #include #include +#include #include "AACube.h" #include "Logging.h" #include "OctalCode.h" #include "Octree.h" #include "OctreeConstants.h" -#include "OctreeElement.h" #include "OctreeLogging.h" #include "OctreeUtils.h" #include "SharedUtil.h" -#include AtomicUIntStat OctreeElement::_octreeMemoryUsage { 0 }; AtomicUIntStat OctreeElement::_octcodeMemoryUsage { 0 }; diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 7108f9a4e4..b938850684 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreePacketData.h" + #include #include #include "OctreeLogging.h" -#include "OctreePacketData.h" #include "NumericalConstants.h" bool OctreePacketData::_debug = false; diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index e6c28f75e8..e6afccab47 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreePersistThread.h" + #include #include @@ -30,7 +32,6 @@ #include #include "OctreeLogging.h" -#include "OctreePersistThread.h" #include "OctreeUtils.h" #include "OctreeDataUtils.h" diff --git a/libraries/octree/src/OctreeProcessor.cpp b/libraries/octree/src/OctreeProcessor.cpp index 43019c7acc..db78e985e6 100644 --- a/libraries/octree/src/OctreeProcessor.cpp +++ b/libraries/octree/src/OctreeProcessor.cpp @@ -8,16 +8,17 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeProcessor.h" + +#include #include -#include #include #include #include #include "OctreeLogging.h" -#include "OctreeProcessor.h" OctreeProcessor::OctreeProcessor() : _tree(NULL), diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index b2efdfd595..d8ff6ba0ec 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctreeSceneStats.h" + #include #include #include @@ -20,8 +22,6 @@ #include "OctreePacketData.h" #include "OctreeElement.h" #include "OctreeLogging.h" -#include "OctreeSceneStats.h" - const int samples = 100; OctreeSceneStats::OctreeSceneStats() : diff --git a/libraries/octree/src/OctreeScriptingInterface.cpp b/libraries/octree/src/OctreeScriptingInterface.cpp index 618e8ac469..b1729c649e 100644 --- a/libraries/octree/src/OctreeScriptingInterface.cpp +++ b/libraries/octree/src/OctreeScriptingInterface.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "OctreeScriptingInterface.h" +#include + OctreeScriptingInterface::OctreeScriptingInterface(OctreeEditPacketSender* packetSender) : _packetSender(packetSender), _managedPacketSender(false), diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 68f21eea87..a801392b66 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityMotionState.h" + #include #include @@ -19,7 +21,6 @@ #include #include "BulletUtil.h" -#include "EntityMotionState.h" #include "PhysicsEngine.h" #include "PhysicsHelpers.h" #include "PhysicsLogging.h" diff --git a/libraries/physics/src/MeshMassProperties.cpp b/libraries/physics/src/MeshMassProperties.cpp index a6a33932aa..ad4208e6a1 100644 --- a/libraries/physics/src/MeshMassProperties.cpp +++ b/libraries/physics/src/MeshMassProperties.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "MeshMassProperties.h" + #include #include -#include "MeshMassProperties.h" - // this method is included for unit test verification void computeBoxInertia(btScalar mass, const btVector3& diagonal, btMatrix3x3& inertia) { // formula for box inertia tensor: diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index 87732ded03..dfcf1aba33 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "EntitySimulation.h" - #include "ObjectAction.h" +#include "EntitySimulation.h" + #include "PhysicsLogging.h" diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index e90862266b..4c2ed35f8e 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "QVariantGLM.h" - #include "ObjectActionOffset.h" +#include "QVariantGLM.h" + #include "PhysicsLogging.h" diff --git a/libraries/physics/src/ObjectActionTractor.cpp b/libraries/physics/src/ObjectActionTractor.cpp index 9b2da22665..a48989be33 100644 --- a/libraries/physics/src/ObjectActionTractor.cpp +++ b/libraries/physics/src/ObjectActionTractor.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "QVariantGLM.h" - #include "ObjectActionTractor.h" +#include "QVariantGLM.h" + #include "PhysicsLogging.h" const float TRACTOR_MAX_SPEED = 10.0f; diff --git a/libraries/physics/src/ObjectActionTravelOriented.cpp b/libraries/physics/src/ObjectActionTravelOriented.cpp index accade8695..c93cce2482 100644 --- a/libraries/physics/src/ObjectActionTravelOriented.cpp +++ b/libraries/physics/src/ObjectActionTravelOriented.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ObjectActionTravelOriented.h" + #include #include "QVariantGLM.h" -#include "ObjectActionTravelOriented.h" #include "PhysicsLogging.h" const uint16_t ObjectActionTravelOriented::actionVersion = 1; diff --git a/libraries/physics/src/ObjectConstraint.cpp b/libraries/physics/src/ObjectConstraint.cpp index 54fd4777e0..38467b1d83 100644 --- a/libraries/physics/src/ObjectConstraint.cpp +++ b/libraries/physics/src/ObjectConstraint.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "EntitySimulation.h" - #include "ObjectConstraint.h" +#include "EntitySimulation.h" + #include "PhysicsLogging.h" ObjectConstraint::ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) : diff --git a/libraries/physics/src/ObjectConstraintBallSocket.cpp b/libraries/physics/src/ObjectConstraintBallSocket.cpp index 4736f2c9e2..b7a186e187 100644 --- a/libraries/physics/src/ObjectConstraintBallSocket.cpp +++ b/libraries/physics/src/ObjectConstraintBallSocket.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ObjectConstraintBallSocket.h" + #include #include "QVariantGLM.h" #include "EntityTree.h" -#include "ObjectConstraintBallSocket.h" #include "PhysicsLogging.h" diff --git a/libraries/physics/src/ObjectConstraintConeTwist.cpp b/libraries/physics/src/ObjectConstraintConeTwist.cpp index 47228c1c16..e2b86a9e0f 100644 --- a/libraries/physics/src/ObjectConstraintConeTwist.cpp +++ b/libraries/physics/src/ObjectConstraintConeTwist.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ObjectConstraintConeTwist.h" + #include #include "QVariantGLM.h" #include "EntityTree.h" -#include "ObjectConstraintConeTwist.h" #include "PhysicsLogging.h" const uint16_t CONE_TWIST_VERSION_WITH_UNUSED_PAREMETERS = 1; diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index 4793741391..0a01f413dc 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ObjectConstraintHinge.h" + #include #include "QVariantGLM.h" #include "EntityTree.h" -#include "ObjectConstraintHinge.h" #include "PhysicsLogging.h" diff --git a/libraries/physics/src/ObjectConstraintSlider.cpp b/libraries/physics/src/ObjectConstraintSlider.cpp index da5bba7f4d..4776e0e4a6 100644 --- a/libraries/physics/src/ObjectConstraintSlider.cpp +++ b/libraries/physics/src/ObjectConstraintSlider.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ObjectConstraintSlider.h" + #include #include "QVariantGLM.h" #include "EntityTree.h" -#include "ObjectConstraintSlider.h" #include "PhysicsLogging.h" diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp index 5bbb5981d1..3341025a8f 100644 --- a/libraries/physics/src/ObjectDynamic.cpp +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "EntitySimulation.h" - #include "ObjectDynamic.h" +#include "EntitySimulation.h" + #include "PhysicsLogging.h" diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index b11e21366e..64d2368207 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ObjectMotionState.h" + #include #include "BulletUtil.h" -#include "ObjectMotionState.h" #include "PhysicsEngine.h" #include "PhysicsHelpers.h" #include "PhysicsLogging.h" diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 50d516c256..83ffa21a55 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -9,18 +9,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "PhysicsEngine.h" #include #include #include +#include #include #include "CharacterController.h" #include "ObjectMotionState.h" -#include "PhysicsEngine.h" #include "PhysicsHelpers.h" #include "PhysicsDebugDraw.h" #include "ThreadSafeDynamicsWorld.h" diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index 5abeb022aa..8057eb0e0c 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -9,11 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ShapeFactory.h" + #include #include // for MILLIMETERS_PER_METER -#include "ShapeFactory.h" #include "BulletUtil.h" diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 97b9e5dab1..ef7a4a1749 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "ShapeManager.h" #include +#include + #include "ShapeFactory.h" -#include "ShapeManager.h" ShapeManager::ShapeManager() { } diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index 5b8c0d5843..3f24851dce 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -15,9 +15,10 @@ * Copied and modified from btDiscreteDynamicsWorld.cpp by AndrewMeadows on 2014.11.12. * */ +#include "ThreadSafeDynamicsWorld.h" + #include -#include "ThreadSafeDynamicsWorld.h" #include "Profile.h" ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld( diff --git a/libraries/recording/src/recording/ClipCache.cpp b/libraries/recording/src/recording/ClipCache.cpp index 0fbbf1bc8e..c63350de7f 100644 --- a/libraries/recording/src/recording/ClipCache.cpp +++ b/libraries/recording/src/recording/ClipCache.cpp @@ -6,11 +6,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ClipCache.h" + #include #include -#include "ClipCache.h" #include "impl/PointerClip.h" #include "Logging.h" diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index c526f16b75..2ac8e77898 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -#include +#include "AmbientOcclusionEffect.h" #include //min max and more +#include #include #include @@ -22,7 +22,6 @@ #include "RenderUtilsLogging.h" #include "DeferredLightingEffect.h" -#include "AmbientOcclusionEffect.h" #include "TextureCache.h" #include "FramebufferCache.h" #include "DependencyManager.h" @@ -543,4 +542,4 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex }); } - \ No newline at end of file + diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index c9aa1b8f71..2173aef76a 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AntialiasingEffect.h" #include @@ -17,7 +18,6 @@ #include #include -#include "AntialiasingEffect.h" #include "StencilMaskPass.h" #include "TextureCache.h" #include "DependencyManager.h" diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 854ff71e20..ceac4ae3c8 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ViewFrustum.h" - #include "LightStage.h" #include +#include "ViewFrustum.h" + std::string LightStage::_stageName { "LIGHT_STAGE"}; const glm::mat4 LightStage::Shadow::_biasMatrix{ 0.5, 0.0, 0.0, 0.0, diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index a3abb24afe..b02266e67b 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -10,10 +10,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "RenderPipelines.h" + #include #include #include +#include #include "StencilMaskPass.h" #include "DeferredLightingEffect.h" @@ -615,9 +618,6 @@ void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state) { skinModelShadowFadeDualQuatProgram, state); } -#include "RenderPipelines.h" -#include - // FIXME find a better way to setup the default textures void RenderPipelines::bindMaterial(const graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures) { if (!material) { diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 8aabffea46..3a7555f790 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -9,19 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "DrawTask.h" -#include "Logging.h" #include #include +#include #include #include #include #include +#include "Logging.h" + #include "drawItemBounds_vert.h" #include "drawItemBounds_frag.h" diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 35cc66315b..703acc5fa6 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "DependencyManager.h" -#include "Logging.h" #include "ShapePipeline.h" #include +#include "DependencyManager.h" +#include "Logging.h" + using namespace render; ShapePipeline::CustomFactoryMap ShapePipeline::_globalCustomFactoryMap; @@ -182,4 +183,4 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke } return shapePipeline; -} \ No newline at end of file +} diff --git a/libraries/script-engine/src/ArrayBufferClass.cpp b/libraries/script-engine/src/ArrayBufferClass.cpp index 4a06dee391..f64dbeffd6 100644 --- a/libraries/script-engine/src/ArrayBufferClass.cpp +++ b/libraries/script-engine/src/ArrayBufferClass.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ArrayBufferClass.h" + #include #include "ArrayBufferPrototype.h" @@ -16,8 +18,6 @@ #include "ScriptEngine.h" #include "TypedArrays.h" -#include "ArrayBufferClass.h" - static const QString CLASS_NAME = "ArrayBuffer"; diff --git a/libraries/script-engine/src/ArrayBufferPrototype.cpp b/libraries/script-engine/src/ArrayBufferPrototype.cpp index 9739f67381..d75482aa2e 100644 --- a/libraries/script-engine/src/ArrayBufferPrototype.cpp +++ b/libraries/script-engine/src/ArrayBufferPrototype.cpp @@ -9,13 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ArrayBufferPrototype.h" + #include #include #include #include "ArrayBufferClass.h" -#include "ArrayBufferPrototype.h" static const int QCOMPRESS_HEADER_POSITION = 0; static const int QCOMPRESS_HEADER_SIZE = 4; diff --git a/libraries/script-engine/src/BatchLoader.cpp b/libraries/script-engine/src/BatchLoader.cpp index 0c65d5c6f0..4e2943d536 100644 --- a/libraries/script-engine/src/BatchLoader.cpp +++ b/libraries/script-engine/src/BatchLoader.cpp @@ -9,15 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "BatchLoader.h" + #include #include - #include #include -#include "ScriptEngineLogging.h" -#include "BatchLoader.h" + #include #include + +#include "ScriptEngineLogging.h" #include "ResourceManager.h" #include "ScriptEngines.h" #include "ScriptCache.h" diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.cpp b/libraries/script-engine/src/ConsoleScriptingInterface.cpp index b4ef98938d..60de04aa9e 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.cpp +++ b/libraries/script-engine/src/ConsoleScriptingInterface.cpp @@ -15,8 +15,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "ConsoleScriptingInterface.h" + +#include + #include "ScriptEngine.h" #define INDENTATION 4 // 1 Tab - 4 spaces diff --git a/libraries/script-engine/src/DataViewClass.cpp b/libraries/script-engine/src/DataViewClass.cpp index a65bdff617..3cc5443973 100644 --- a/libraries/script-engine/src/DataViewClass.cpp +++ b/libraries/script-engine/src/DataViewClass.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "DataViewPrototype.h" - #include "DataViewClass.h" +#include "DataViewPrototype.h" + Q_DECLARE_METATYPE(QByteArray*) static const QString DATA_VIEW_NAME = "DataView"; @@ -91,4 +91,4 @@ QString DataViewClass::name() const { QScriptValue DataViewClass::prototype() const { return _proto; -} \ No newline at end of file +} diff --git a/libraries/script-engine/src/DataViewPrototype.cpp b/libraries/script-engine/src/DataViewPrototype.cpp index 8bab574f33..ef757a5cb4 100644 --- a/libraries/script-engine/src/DataViewPrototype.cpp +++ b/libraries/script-engine/src/DataViewPrototype.cpp @@ -8,14 +8,15 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +#include "DataViewPrototype.h" + #include #include #include "DataViewClass.h" -#include "DataViewPrototype.h" - Q_DECLARE_METATYPE(QByteArray*) DataViewPrototype::DataViewPrototype(QObject* parent) : QObject(parent) { diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index abdd934e5a..94c074d44e 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EventTypes.h" + #include "KeyEvent.h" #include "MouseEvent.h" #include "SpatialEvent.h" @@ -16,8 +18,6 @@ #include "TouchEvent.h" #include "WheelEvent.h" -#include "EventTypes.h" - void registerEventTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, KeyEvent::toScriptValue, KeyEvent::fromScriptValue); qScriptRegisterMetaType(engine, MouseEvent::toScriptValue, MouseEvent::fromScriptValue); diff --git a/libraries/script-engine/src/KeyEvent.cpp b/libraries/script-engine/src/KeyEvent.cpp index 581f9a816b..b0e622a774 100644 --- a/libraries/script-engine/src/KeyEvent.cpp +++ b/libraries/script-engine/src/KeyEvent.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "KeyEvent.h" + #include #include #include "ScriptEngineLogging.h" -#include "KeyEvent.h" - KeyEvent::KeyEvent() : key(0), text(""), diff --git a/libraries/script-engine/src/Mat4.cpp b/libraries/script-engine/src/Mat4.cpp index 15015782e2..3e75d815c3 100644 --- a/libraries/script-engine/src/Mat4.cpp +++ b/libraries/script-engine/src/Mat4.cpp @@ -9,14 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include +#include "Mat4.h" + #include #include #include + +#include +#include + #include "ScriptEngineLogging.h" #include "ScriptEngine.h" -#include "Mat4.h" glm::mat4 Mat4::multiply(const glm::mat4& m1, const glm::mat4& m2) const { return m1 * m2; diff --git a/libraries/script-engine/src/MenuItemProperties.cpp b/libraries/script-engine/src/MenuItemProperties.cpp index 40254eeccb..2662ba406d 100644 --- a/libraries/script-engine/src/MenuItemProperties.cpp +++ b/libraries/script-engine/src/MenuItemProperties.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include #include "MenuItemProperties.h" +#include +#include MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& menuItemName, diff --git a/libraries/script-engine/src/MouseEvent.cpp b/libraries/script-engine/src/MouseEvent.cpp index 20bac96087..1bace0425f 100644 --- a/libraries/script-engine/src/MouseEvent.cpp +++ b/libraries/script-engine/src/MouseEvent.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "MouseEvent.h" + #include #include -#include "MouseEvent.h" - MouseEvent::MouseEvent() : x(0.0f), y(0.0f), @@ -104,4 +104,4 @@ QScriptValue MouseEvent::toScriptValue(QScriptEngine* engine, const MouseEvent& void MouseEvent::fromScriptValue(const QScriptValue& object, MouseEvent& event) { // nothing for now... -} \ No newline at end of file +} diff --git a/libraries/script-engine/src/MouseEvent.h b/libraries/script-engine/src/MouseEvent.h index 0fbc688e5f..d9b00a8e01 100644 --- a/libraries/script-engine/src/MouseEvent.h +++ b/libraries/script-engine/src/MouseEvent.h @@ -13,6 +13,9 @@ #define hifi_MouseEvent_h #include +#include + +class QScriptEngine; class MouseEvent { public: @@ -38,4 +41,4 @@ public: Q_DECLARE_METATYPE(MouseEvent) -#endif // hifi_MouseEvent_h \ No newline at end of file +#endif // hifi_MouseEvent_h diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index a6f7acffc8..afff0a6b03 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -9,16 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Quat.h" + #include +#include #include #include -#include -#include + #include "ScriptEngineLogging.h" #include "ScriptEngine.h" -#include "Quat.h" quat Quat::normalize(const glm::quat& q) { return glm::normalize(q); diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 254757dece..1ccdfdbf31 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -20,6 +20,8 @@ #include #include +#include + /**jsdoc * A quaternion value. See also the {@link Quat(0)|Quat} object. * @typedef {object} Quat diff --git a/libraries/script-engine/src/ScriptAudioInjector.cpp b/libraries/script-engine/src/ScriptAudioInjector.cpp index 516f62401f..8b51377bff 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.cpp +++ b/libraries/script-engine/src/ScriptAudioInjector.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ScriptEngineLogging.h" #include "ScriptAudioInjector.h" +#include "ScriptEngineLogging.h" + QScriptValue injectorToScriptValue(QScriptEngine* engine, ScriptAudioInjector* const& in) { // The AudioScriptingInterface::playSound method can return null, so we need to account for that. if (!in) { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 4915a2dc8b..9a383454d4 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ScriptEngine.h" + #include #include @@ -67,7 +69,6 @@ #include "ScriptAvatarData.h" #include "ScriptCache.h" #include "ScriptEngineLogging.h" -#include "ScriptEngine.h" #include "TypedArrays.h" #include "XMLHttpRequestClass.h" #include "WebSocketClass.h" diff --git a/libraries/script-engine/src/ScriptUUID.cpp b/libraries/script-engine/src/ScriptUUID.cpp index ee15f1a760..f88803c87c 100644 --- a/libraries/script-engine/src/ScriptUUID.cpp +++ b/libraries/script-engine/src/ScriptUUID.cpp @@ -11,11 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ScriptUUID.h" + #include #include "ScriptEngineLogging.h" #include "ScriptEngine.h" -#include "ScriptUUID.h" QUuid ScriptUUID::fromString(const QString& s) { return QUuid(s); diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h index 9b61f451c5..0af0c1cf8e 100644 --- a/libraries/script-engine/src/ScriptUUID.h +++ b/libraries/script-engine/src/ScriptUUID.h @@ -15,6 +15,7 @@ #define hifi_ScriptUUID_h #include +#include #include /**jsdoc diff --git a/libraries/script-engine/src/SpatialEvent.cpp b/libraries/script-engine/src/SpatialEvent.cpp index f20a0c2b1e..d06cc556d3 100644 --- a/libraries/script-engine/src/SpatialEvent.cpp +++ b/libraries/script-engine/src/SpatialEvent.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "SpatialEvent.h" +#include + SpatialEvent::SpatialEvent() : locTranslation(0.0f), locRotation(), @@ -43,4 +43,4 @@ QScriptValue SpatialEvent::toScriptValue(QScriptEngine* engine, const SpatialEve void SpatialEvent::fromScriptValue(const QScriptValue& object,SpatialEvent& event) { // nothing for now... -} \ No newline at end of file +} diff --git a/libraries/script-engine/src/TouchEvent.cpp b/libraries/script-engine/src/TouchEvent.cpp index 097639d4e8..6ff591decf 100644 --- a/libraries/script-engine/src/TouchEvent.cpp +++ b/libraries/script-engine/src/TouchEvent.cpp @@ -9,15 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TouchEvent.h" + #include #include -#include #include #include -#include "TouchEvent.h" - TouchEvent::TouchEvent() : x(0.0f), y(0.0f), diff --git a/libraries/script-engine/src/TouchEvent.h b/libraries/script-engine/src/TouchEvent.h index d9eedf50d0..62cb1b1801 100644 --- a/libraries/script-engine/src/TouchEvent.h +++ b/libraries/script-engine/src/TouchEvent.h @@ -13,8 +13,13 @@ #define hifi_TouchEvent_h #include + +#include #include +class QScriptValue; +class QScriptEngine; + class TouchEvent { public: TouchEvent(); @@ -54,4 +59,4 @@ private: Q_DECLARE_METATYPE(TouchEvent) -#endif // hifi_TouchEvent_h \ No newline at end of file +#endif // hifi_TouchEvent_h diff --git a/libraries/script-engine/src/TypedArrayPrototype.cpp b/libraries/script-engine/src/TypedArrayPrototype.cpp index 4de948e806..a1f3ff87e8 100644 --- a/libraries/script-engine/src/TypedArrayPrototype.cpp +++ b/libraries/script-engine/src/TypedArrayPrototype.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "TypedArrays.h" - #include "TypedArrayPrototype.h" +#include "TypedArrays.h" + Q_DECLARE_METATYPE(QByteArray*) TypedArrayPrototype::TypedArrayPrototype(QObject* parent) : QObject(parent) { diff --git a/libraries/script-engine/src/TypedArrays.cpp b/libraries/script-engine/src/TypedArrays.cpp index 4d5181ff33..f2c3d3fd3d 100644 --- a/libraries/script-engine/src/TypedArrays.cpp +++ b/libraries/script-engine/src/TypedArrays.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "TypedArrays.h" + #include #include "ScriptEngine.h" #include "TypedArrayPrototype.h" -#include "TypedArrays.h" - Q_DECLARE_METATYPE(QByteArray*) TypedArray::TypedArray(ScriptEngine* scriptEngine, QString name) : ArrayBufferViewClass(scriptEngine) { diff --git a/libraries/script-engine/src/UndoStackScriptingInterface.cpp b/libraries/script-engine/src/UndoStackScriptingInterface.cpp index 17bf8b1aa6..1171625c04 100644 --- a/libraries/script-engine/src/UndoStackScriptingInterface.cpp +++ b/libraries/script-engine/src/UndoStackScriptingInterface.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "UndoStackScriptingInterface.h" + #include #include #include #include -#include "UndoStackScriptingInterface.h" - UndoStackScriptingInterface::UndoStackScriptingInterface(QUndoStack* undoStack) : _undoStack(undoStack) { } diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp index c21f96cd47..2d3d4454c3 100644 --- a/libraries/script-engine/src/Vec3.cpp +++ b/libraries/script-engine/src/Vec3.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Vec3.h" + #include #include @@ -16,11 +18,10 @@ #include #include -#include "ScriptEngineLogging.h" #include "NumericalConstants.h" -#include "Vec3.h" - #include "ScriptEngine.h" +#include "ScriptEngineLogging.h" + float Vec3::orientedAngle(const glm::vec3& v1, const glm::vec3& v2, const glm::vec3& v3) { float radians = glm::orientedAngle(glm::normalize(v1), glm::normalize(v2), glm::normalize(v3)); diff --git a/libraries/script-engine/src/WebSocketClass.cpp b/libraries/script-engine/src/WebSocketClass.cpp index 76faaab415..56753f07d1 100644 --- a/libraries/script-engine/src/WebSocketClass.cpp +++ b/libraries/script-engine/src/WebSocketClass.cpp @@ -12,9 +12,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ScriptEngine.h" #include "WebSocketClass.h" +#include "ScriptEngine.h" + WebSocketClass::WebSocketClass(QScriptEngine* engine, QString url) : _webSocket(new QWebSocket()), _engine(engine) diff --git a/libraries/script-engine/src/WebSocketServerClass.cpp b/libraries/script-engine/src/WebSocketServerClass.cpp index 3b723d5b3f..860170a3f9 100644 --- a/libraries/script-engine/src/WebSocketServerClass.cpp +++ b/libraries/script-engine/src/WebSocketServerClass.cpp @@ -11,9 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ScriptEngine.h" #include "WebSocketServerClass.h" +#include "ScriptEngine.h" + WebSocketServerClass::WebSocketServerClass(QScriptEngine* engine, const QString& serverName, const quint16 port) : _webSocketServer(serverName, QWebSocketServer::SslMode::NonSecureMode), _engine(engine) diff --git a/libraries/script-engine/src/WheelEvent.cpp b/libraries/script-engine/src/WheelEvent.cpp index 70004d0d3f..a0a897c991 100644 --- a/libraries/script-engine/src/WheelEvent.cpp +++ b/libraries/script-engine/src/WheelEvent.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include - #include "WheelEvent.h" +#include +#include + WheelEvent::WheelEvent() : x(0.0f), y(0.0f), @@ -99,4 +99,4 @@ QScriptValue WheelEvent::toScriptValue(QScriptEngine* engine, const WheelEvent& void WheelEvent::fromScriptValue(const QScriptValue& object, WheelEvent& event) { // nothing for now... -} \ No newline at end of file +} diff --git a/libraries/script-engine/src/WheelEvent.h b/libraries/script-engine/src/WheelEvent.h index edac4bc3c3..88ac828578 100644 --- a/libraries/script-engine/src/WheelEvent.h +++ b/libraries/script-engine/src/WheelEvent.h @@ -12,8 +12,12 @@ #ifndef hifi_WheelEvent_h #define hifi_WheelEvent_h +#include #include +class QScriptValue; +class QScriptEngine; + class WheelEvent { public: WheelEvent(); @@ -37,4 +41,4 @@ public: Q_DECLARE_METATYPE(WheelEvent) -#endif // hifi_WheelEvent_h \ No newline at end of file +#endif // hifi_WheelEvent_h diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index 62384f9d97..ebc459b2d1 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "XMLHttpRequestClass.h" + #include #include @@ -20,7 +22,6 @@ #include #include "ScriptEngine.h" -#include "XMLHttpRequestClass.h" const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/api/"; diff --git a/libraries/shared/src/AACube.cpp b/libraries/shared/src/AACube.cpp index 8cff3255b3..7dd2f8cb5b 100644 --- a/libraries/shared/src/AACube.cpp +++ b/libraries/shared/src/AACube.cpp @@ -9,8 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AABox.h" #include "AACube.h" + +#include "AABox.h" #include "Extents.h" #include "GeometryUtil.h" #include "NumericalConstants.h" diff --git a/libraries/shared/src/CubeProjectedPolygon.cpp b/libraries/shared/src/CubeProjectedPolygon.cpp index 04d6e8bb4e..acd2fc11d6 100644 --- a/libraries/shared/src/CubeProjectedPolygon.cpp +++ b/libraries/shared/src/CubeProjectedPolygon.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "CubeProjectedPolygon.h" + #include #include @@ -16,8 +18,6 @@ #include "GeometryUtil.h" #include "SharedUtil.h" #include "SharedLogging.h" -#include "CubeProjectedPolygon.h" - glm::vec2 BoundingRectangle::getVertex(int vertexNumber) const { switch (vertexNumber) { diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index 309cb30728..3b7a6cee40 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -8,8 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -#include - +#include "GPUIdent.h" #ifdef Q_OS_WIN #include @@ -24,8 +23,9 @@ #include #endif +#include + #include "SharedLogging.h" -#include "GPUIdent.h" GPUIdent GPUIdent::_instance {}; diff --git a/libraries/shared/src/GPUIdent.h b/libraries/shared/src/GPUIdent.h index 8615e61b08..f780a4ddbd 100644 --- a/libraries/shared/src/GPUIdent.h +++ b/libraries/shared/src/GPUIdent.h @@ -16,6 +16,8 @@ #include +#include + class GPUIdent { public: diff --git a/libraries/shared/src/GenericThread.cpp b/libraries/shared/src/GenericThread.cpp index 230b9590f1..e35c74e68a 100644 --- a/libraries/shared/src/GenericThread.cpp +++ b/libraries/shared/src/GenericThread.cpp @@ -9,11 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include - #include "GenericThread.h" +#include +#include GenericThread::GenericThread() : _stopThread(false), diff --git a/libraries/shared/src/Gzip.cpp b/libraries/shared/src/Gzip.cpp index 25e214fffb..06b499b88a 100644 --- a/libraries/shared/src/Gzip.cpp +++ b/libraries/shared/src/Gzip.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include "Gzip.h" +#include + const int GZIP_WINDOWS_BIT = 31; const int GZIP_CHUNK_SIZE = 4096; const int DEFAULT_MEM_LEVEL = 8; diff --git a/libraries/shared/src/LogUtils.cpp b/libraries/shared/src/LogUtils.cpp index 73667116a0..11a4665ab1 100644 --- a/libraries/shared/src/LogUtils.cpp +++ b/libraries/shared/src/LogUtils.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "LogUtils.h" +#include + void LogUtils::init() { #ifdef Q_OS_WIN // Windows applications buffer stdout/err hard when not run from a terminal, diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index c7ad4a790d..7f7d03c335 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OctalCode.h" + #include // std:min #include #include @@ -17,7 +19,6 @@ #include #include "NumericalConstants.h" -#include "OctalCode.h" #include "SharedUtil.h" int numberOfThreeBitSectionsInCode(const unsigned char* octalCode, int maxBytes) { diff --git a/libraries/shared/src/PIDController.cpp b/libraries/shared/src/PIDController.cpp index 790c26ac25..5850e345cb 100644 --- a/libraries/shared/src/PIDController.cpp +++ b/libraries/shared/src/PIDController.cpp @@ -9,11 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include "SharedLogging.h" #include "PIDController.h" +#include + +#include + +#include "SharedLogging.h" + float PIDController::update(float measuredValue, float dt, bool resetAccumulator) { const float error = getMeasuredValueSetpoint() - measuredValue; // Sign is the direction we want measuredValue to go. Positive means go higher. diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 13b3d44eda..c3bc44b7d3 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "PerfStat.h" + #include #include #include @@ -16,8 +18,6 @@ #include #include -#include "PerfStat.h" - #include "NumericalConstants.h" #include "SharedLogging.h" diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp index f75180afb5..9bcc6b732f 100644 --- a/libraries/shared/src/SimpleMovingAverage.cpp +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -9,9 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "SharedUtil.h" #include "SimpleMovingAverage.h" +#include "SharedUtil.h" + SimpleMovingAverage::SimpleMovingAverage(int numSamplesToAverage) : _numSamples(0), _lastEventTimestamp(0), diff --git a/libraries/shared/src/StDev.cpp b/libraries/shared/src/StDev.cpp index 23afd12b98..99280ba42e 100644 --- a/libraries/shared/src/StDev.cpp +++ b/libraries/shared/src/StDev.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "StDev.h" + #include #include #include -#include "StDev.h" - StDev::StDev() : _sampleCount(0) { diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index 876de2e698..9ed0e24593 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "StreamUtils.h" #include -#include "StreamUtils.h" +#include void StreamUtil::dump(std::ostream& s, const QByteArray& buffer) { diff --git a/libraries/shared/src/TriangleSet.cpp b/libraries/shared/src/TriangleSet.cpp index 3f8f748720..d7f685f8d3 100644 --- a/libraries/shared/src/TriangleSet.cpp +++ b/libraries/shared/src/TriangleSet.cpp @@ -9,9 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GLMHelpers.h" #include "TriangleSet.h" +#include "GLMHelpers.h" void TriangleSet::insert(const Triangle& t) { _isBalanced = false; diff --git a/libraries/shared/src/VariantMapToScriptValue.cpp b/libraries/shared/src/VariantMapToScriptValue.cpp index 00fc2cd682..008c3a5d9b 100644 --- a/libraries/shared/src/VariantMapToScriptValue.cpp +++ b/libraries/shared/src/VariantMapToScriptValue.cpp @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include "SharedLogging.h" #include "VariantMapToScriptValue.h" +#include + +#include "SharedLogging.h" QScriptValue variantToScriptValue(QVariant& qValue, QScriptEngine& scriptEngine) { switch(qValue.type()) { diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 3aa70b0897..3e03c13fa4 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ViewFrustum.h" + #include #include @@ -16,15 +18,13 @@ #include #include #include -#include +#include #include "GeometryUtil.h" #include "GLMHelpers.h" #include "NumericalConstants.h" #include "SharedLogging.h" -//#include "OctreeConstants.h" -#include "ViewFrustum.h" using namespace std; diff --git a/libraries/shared/src/shared/StringHelpers.cpp b/libraries/shared/src/shared/StringHelpers.cpp index 1c1730bd5a..39ac23e510 100644 --- a/libraries/shared/src/shared/StringHelpers.cpp +++ b/libraries/shared/src/shared/StringHelpers.cpp @@ -6,10 +6,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "StringHelpers.h" +#include + /// Note: this will not preserve line breaks in the original input. QString simpleWordWrap(const QString& input, int maxCharactersPerLine) { QStringList words = input.split(QRegExp("\\s+")); diff --git a/plugins/pcmCodec/src/PCMCodecManager.cpp b/plugins/pcmCodec/src/PCMCodecManager.cpp index 051f3973a8..04adb367af 100644 --- a/plugins/pcmCodec/src/PCMCodecManager.cpp +++ b/plugins/pcmCodec/src/PCMCodecManager.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "PCMCodecManager.h" + #include #include -#include "PCMCodecManager.h" - const char* PCMCodec::NAME { "pcm" }; void PCMCodec::init() { diff --git a/tests/jitter/src/JitterTests.cpp b/tests/jitter/src/JitterTests.cpp index b09cb40d3e..5c81177b88 100644 --- a/tests/jitter/src/JitterTests.cpp +++ b/tests/jitter/src/JitterTests.cpp @@ -6,6 +6,8 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // +#include "JitterTests.h" + #include #ifdef _WINDOWS #include @@ -23,8 +25,6 @@ #include #include -#include "JitterTests.h" - // Uncomment this to run manually //#define RUN_MANUALLY diff --git a/tests/networking/src/ResourceTests.cpp b/tests/networking/src/ResourceTests.cpp index e83eeb66a0..864d7c9939 100644 --- a/tests/networking/src/ResourceTests.cpp +++ b/tests/networking/src/ResourceTests.cpp @@ -7,14 +7,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ResourceTests.h" + #include #include "ResourceCache.h" #include "NetworkAccessManager.h" #include "DependencyManager.h" -#include "ResourceTests.h" - QTEST_MAIN(ResourceTests) void ResourceTests::initTestCase() { diff --git a/tests/networking/src/SequenceNumberStatsTests.cpp b/tests/networking/src/SequenceNumberStatsTests.cpp index aaaeea53fc..0f01fb5b66 100644 --- a/tests/networking/src/SequenceNumberStatsTests.cpp +++ b/tests/networking/src/SequenceNumberStatsTests.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SequenceNumberStatsTests.h" + #include #include -#include "SequenceNumberStatsTests.h" - QTEST_MAIN(SequenceNumberStatsTests) const quint32 UINT16_RANGE = std::numeric_limits::max() + 1; diff --git a/tests/octree/src/AABoxCubeTests.cpp b/tests/octree/src/AABoxCubeTests.cpp index 8180e6f674..4e0a75e3b9 100644 --- a/tests/octree/src/AABoxCubeTests.cpp +++ b/tests/octree/src/AABoxCubeTests.cpp @@ -9,11 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AABoxCubeTests.h" + #include #include -#include "AABoxCubeTests.h" - QTEST_MAIN(AABoxCubeTests) void AABoxCubeTests::raycastOutHitsXMinFace() { diff --git a/tests/octree/src/ModelTests.cpp b/tests/octree/src/ModelTests.cpp index c2d170da9a..f3e17a56a5 100644 --- a/tests/octree/src/ModelTests.cpp +++ b/tests/octree/src/ModelTests.cpp @@ -12,6 +12,9 @@ // * need to add expected results and accumulation of test success/failure // +#include "ModelTests.h" // needs to be EntityTests.h soon +//#include "EntityTests.h" + #include #include @@ -22,9 +25,6 @@ #include #include -//#include "EntityTests.h" -#include "ModelTests.h" // needs to be EntityTests.h soon - QTEST_MAIN(EntityTests) /* diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 81300a1293..ae04313a6a 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -12,6 +12,8 @@ // * need to add expected results and accumulation of test success/failure // +#include "OctreeTests.h" + #include #include @@ -23,8 +25,6 @@ #include #include -#include "OctreeTests.h" - enum ExamplePropertyList { EXAMPLE_PROP_PAGED_PROPERTY, EXAMPLE_PROP_CUSTOM_PROPERTIES_INCLUDED, diff --git a/tests/physics/src/ShapeInfoTests.cpp b/tests/physics/src/ShapeInfoTests.cpp index 79d0092dc3..efc88a4032 100644 --- a/tests/physics/src/ShapeInfoTests.cpp +++ b/tests/physics/src/ShapeInfoTests.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ShapeInfoTests.h" + #include #include @@ -19,8 +21,6 @@ #include #include -#include "ShapeInfoTests.h" - QTEST_MAIN(ShapeInfoTests) // Enable this to manually run testHashCollisions diff --git a/tests/physics/src/ShapeManagerTests.cpp b/tests/physics/src/ShapeManagerTests.cpp index f214601a42..393bfdcd07 100644 --- a/tests/physics/src/ShapeManagerTests.cpp +++ b/tests/physics/src/ShapeManagerTests.cpp @@ -9,13 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ShapeManagerTests.h" + #include + #include #include #include -#include "ShapeManagerTests.h" - QTEST_MAIN(ShapeManagerTests) void ShapeManagerTests::testShapeAccounting() { diff --git a/tests/shared/src/AABoxTests.cpp b/tests/shared/src/AABoxTests.cpp index 2e9dfab497..865a82e86c 100644 --- a/tests/shared/src/AABoxTests.cpp +++ b/tests/shared/src/AABoxTests.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "AABoxTests.h" +#include + #include #include #include diff --git a/tests/shared/src/AACubeTests.cpp b/tests/shared/src/AACubeTests.cpp index 177daf89f1..4d684b4677 100644 --- a/tests/shared/src/AACubeTests.cpp +++ b/tests/shared/src/AACubeTests.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "AACubeTests.h" +#include + #include #include #include diff --git a/tests/shared/src/DualQuaternionTests.cpp b/tests/shared/src/DualQuaternionTests.cpp index fe14d9d166..276eb44f64 100644 --- a/tests/shared/src/DualQuaternionTests.cpp +++ b/tests/shared/src/DualQuaternionTests.cpp @@ -8,10 +8,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "DualQuaternionTests.h" +#include + #include #include #include diff --git a/tests/shared/src/GeometryUtilTests.cpp b/tests/shared/src/GeometryUtilTests.cpp index eb9be4987f..9b4f0f250f 100644 --- a/tests/shared/src/GeometryUtilTests.cpp +++ b/tests/shared/src/GeometryUtilTests.cpp @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "GeometryUtilTests.h" +#include + #include #include #include diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index 4711dc4102..cfede87c53 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -9,10 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ACClientApp.h" + #include #include #include #include + #include #include #include @@ -20,8 +23,6 @@ #include #include -#include "ACClientApp.h" - ACClientApp::ACClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 526065b2f7..c688ba9c82 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ATPClientApp.h" + #include #include #include @@ -25,8 +27,6 @@ #include #include -#include "ATPClientApp.h" - #define HIGH_FIDELITY_ATP_CLIENT_USER_AGENT "Mozilla/5.0 (HighFidelityATPClient)" #define TIMEOUT_MILLISECONDS 8000 diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index f9e7a76142..0301fad6f4 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -9,15 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ICEClientApp.h" + #include #include #include + #include #include #include -#include "ICEClientApp.h" - ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { diff --git a/tools/oven/src/BakerCLI.cpp b/tools/oven/src/BakerCLI.cpp index 35550cdca8..a7b8401269 100644 --- a/tools/oven/src/BakerCLI.cpp +++ b/tools/oven/src/BakerCLI.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "BakerCLI.h" + #include #include #include @@ -16,7 +18,6 @@ #include "OvenCLIApplication.h" #include "ModelBakingLoggingCategory.h" -#include "BakerCLI.h" #include "FBXBaker.h" #include "JSBaker.h" #include "TextureBaker.h" diff --git a/tools/oven/src/OvenCLIApplication.cpp b/tools/oven/src/OvenCLIApplication.cpp index 2fb8ea03f2..ab3178db01 100644 --- a/tools/oven/src/OvenCLIApplication.cpp +++ b/tools/oven/src/OvenCLIApplication.cpp @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OvenCLIApplication.h" + #include #include #include "BakerCLI.h" -#include "OvenCLIApplication.h" - static const QString CLI_INPUT_PARAMETER = "i"; static const QString CLI_OUTPUT_PARAMETER = "o"; static const QString CLI_TYPE_PARAMETER = "t"; diff --git a/tools/oven/src/ui/BakeWidget.cpp b/tools/oven/src/ui/BakeWidget.cpp index 43f4c50328..931ef1de43 100644 --- a/tools/oven/src/ui/BakeWidget.cpp +++ b/tools/oven/src/ui/BakeWidget.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "BakeWidget.h" + #include #include "../OvenGUIApplication.h" -#include "BakeWidget.h" - BakeWidget::BakeWidget(QWidget* parent, Qt::WindowFlags flags) : QWidget(parent, flags) { diff --git a/tools/oven/src/ui/DomainBakeWidget.cpp b/tools/oven/src/ui/DomainBakeWidget.cpp index bf79319458..1121041e39 100644 --- a/tools/oven/src/ui/DomainBakeWidget.cpp +++ b/tools/oven/src/ui/DomainBakeWidget.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainBakeWidget.h" + #include #include @@ -23,8 +25,6 @@ #include "../OvenGUIApplication.h" -#include "DomainBakeWidget.h" - static const QString DOMAIN_NAME_SETTING_KEY = "domain_name"; static const QString EXPORT_DIR_SETTING_KEY = "domain_export_directory"; static const QString BROWSE_START_DIR_SETTING_KEY = "domain_search_directory"; diff --git a/tools/oven/src/ui/ModelBakeWidget.cpp b/tools/oven/src/ui/ModelBakeWidget.cpp index f80185df0f..9fa586871e 100644 --- a/tools/oven/src/ui/ModelBakeWidget.cpp +++ b/tools/oven/src/ui/ModelBakeWidget.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelBakeWidget.h" + #include #include #include @@ -26,7 +28,6 @@ #include "OvenMainWindow.h" #include "FBXBaker.h" #include "OBJBaker.h" -#include "ModelBakeWidget.h" static const auto EXPORT_DIR_SETTING_KEY = "model_export_directory"; diff --git a/tools/oven/src/ui/ModesWidget.cpp b/tools/oven/src/ui/ModesWidget.cpp index 624aa949cc..1fdfce2c97 100644 --- a/tools/oven/src/ui/ModesWidget.cpp +++ b/tools/oven/src/ui/ModesWidget.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModesWidget.h" + #include #include #include @@ -17,8 +19,6 @@ #include "ModelBakeWidget.h" #include "SkyboxBakeWidget.h" -#include "ModesWidget.h" - ModesWidget::ModesWidget(QWidget* parent, Qt::WindowFlags flags) : QWidget(parent, flags) { diff --git a/tools/oven/src/ui/OvenMainWindow.cpp b/tools/oven/src/ui/OvenMainWindow.cpp index bebc2fa7dc..59cad3aac5 100644 --- a/tools/oven/src/ui/OvenMainWindow.cpp +++ b/tools/oven/src/ui/OvenMainWindow.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "OvenMainWindow.h" + #include #include "ModesWidget.h" -#include "OvenMainWindow.h" - OvenMainWindow::OvenMainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) { diff --git a/tools/oven/src/ui/ResultsWindow.cpp b/tools/oven/src/ui/ResultsWindow.cpp index 3a37a328de..feb7fbc4f1 100644 --- a/tools/oven/src/ui/ResultsWindow.cpp +++ b/tools/oven/src/ui/ResultsWindow.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ResultsWindow.h" + #include #include #include @@ -17,8 +19,6 @@ #include "OvenMainWindow.h" -#include "ResultsWindow.h" - ResultsWindow::ResultsWindow(QWidget* parent) : QWidget(parent) { diff --git a/tools/oven/src/ui/SkyboxBakeWidget.cpp b/tools/oven/src/ui/SkyboxBakeWidget.cpp index 369b06c39f..71ae0cbab0 100644 --- a/tools/oven/src/ui/SkyboxBakeWidget.cpp +++ b/tools/oven/src/ui/SkyboxBakeWidget.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SkyboxBakeWidget.h" + #include #include #include @@ -21,9 +23,9 @@ #include #include -#include "../OvenGUIApplication.h" +#include -#include "SkyboxBakeWidget.h" +#include "../OvenGUIApplication.h" static const auto EXPORT_DIR_SETTING_KEY = "skybox_export_directory"; static const auto SELECTION_START_DIR_SETTING_KEY = "skybox_search_directory"; diff --git a/tools/vhacd-util/src/VHACDUtilApp.cpp b/tools/vhacd-util/src/VHACDUtilApp.cpp index 4d48bdf2bf..c263dce609 100644 --- a/tools/vhacd-util/src/VHACDUtilApp.cpp +++ b/tools/vhacd-util/src/VHACDUtilApp.cpp @@ -9,10 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "VHACDUtilApp.h" + #include + #include #include -#include "VHACDUtilApp.h" + #include "VHACDUtil.h" #include "PathUtils.h" From 5a3773ba72811d8dfbe04ad0c2703adc87147764 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 4 May 2018 17:08:42 -0700 Subject: [PATCH 160/174] Fix compile error on linux/windows --- interface/src/LocationBookmarks.cpp | 5 ----- interface/src/LocationBookmarks.h | 1 + interface/src/ModelPackager.h | 2 ++ libraries/entities/src/EntityTypes.h | 1 + 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index f29a8f18f9..8415c84282 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -12,16 +12,11 @@ #include "LocationBookmarks.h" #include -#include -#include #include -#include #include -#include #include -#include "MainWindow.h" #include "Menu.h" const QString LocationBookmarks::HOME_BOOKMARK = "Home"; diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index 9a800ba35e..39abea9ba4 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -13,6 +13,7 @@ #define hifi_LocationBookmarks_h #include + #include "Bookmarks.h" class LocationBookmarks : public Bookmarks, public Dependency { diff --git a/interface/src/ModelPackager.h b/interface/src/ModelPackager.h index acd4d85f68..76295e5a85 100644 --- a/interface/src/ModelPackager.h +++ b/interface/src/ModelPackager.h @@ -12,6 +12,8 @@ #ifndef hifi_ModelPackager_h #define hifi_ModelPackager_h +#include + #include #include diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 0e2fca8180..1f3434d254 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -12,6 +12,7 @@ #ifndef hifi_EntityTypes_h #define hifi_EntityTypes_h +#include #include #include From 6a55e67ce9cd01ed29825d14889a1d0d2ad902c6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 5 May 2018 16:39:03 -0700 Subject: [PATCH 161/174] avoid misaligned pointer deref --- libraries/gpu/src/gpu/Texture_ktx.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 0822af3cfb..bb081637be 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -46,13 +46,14 @@ struct GPUKTXPayload { memcpy(data, &_samplerDesc, sizeof(Sampler::Desc)); data += sizeof(Sampler::Desc); - + // We can't copy the bitset in Texture::Usage in a crossplateform manner // So serialize it manually - *(uint32*)data = _usage._flags.to_ulong(); + uint32 usageData = _usage._flags.to_ulong(); + memcpy(data, &usageData, sizeof(uint32)); data += sizeof(uint32); - *(TextureUsageType*)data = _usageType; + memcpy(data, &_usageType, sizeof(TextureUsageType)); data += sizeof(TextureUsageType); return data + PADDING; @@ -77,10 +78,12 @@ struct GPUKTXPayload { memcpy(&_samplerDesc, data, sizeof(Sampler::Desc)); data += sizeof(Sampler::Desc); - + // We can't copy the bitset in Texture::Usage in a crossplateform manner // So unserialize it manually - _usage = Texture::Usage(*(const uint32*)data); + uint32 usageData; + memcpy(&usageData, data, sizeof(uint32)); + _usage = Texture::Usage(usageData); data += sizeof(uint32); _usageType = *(const TextureUsageType*)data; @@ -710,4 +713,4 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E return false; } return true; -} \ No newline at end of file +} From 677c99abd46e429090a4ebd3d85b2f7145e9ea6e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 5 May 2018 20:50:54 -0700 Subject: [PATCH 162/174] use memcpy on _usageType as well --- libraries/gpu/src/gpu/Texture_ktx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index bb081637be..129c125411 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -86,7 +86,7 @@ struct GPUKTXPayload { _usage = Texture::Usage(usageData); data += sizeof(uint32); - _usageType = *(const TextureUsageType*)data; + memcpy(&_usageType, data, sizeof(TextureUsageType)); return true; } From b4cfea2fbc4793bc9f3fddcf8949ab67cf826c19 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sun, 6 May 2018 17:17:06 +0300 Subject: [PATCH 163/174] FB14818 Login page for steam is blank --- interface/resources/qml/LoginDialog/SignInBody.qml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/LoginDialog/SignInBody.qml b/interface/resources/qml/LoginDialog/SignInBody.qml index c4b6c2aee1..9cb1add704 100644 --- a/interface/resources/qml/LoginDialog/SignInBody.qml +++ b/interface/resources/qml/LoginDialog/SignInBody.qml @@ -84,11 +84,9 @@ Item { height: undefined // invalidate so that the image's size sets the height focus: true - style: OriginalStyles.ButtonStyle { - background: Image { - id: buttonImage - source: "../../images/steam-sign-in.png" - } + background: Image { + id: buttonImage + source: "../../images/steam-sign-in.png" } onClicked: signInBody.login() } From 646c0ec987eb285e641ef1ca9a75bfc45f888136 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 7 May 2018 11:56:47 -0700 Subject: [PATCH 164/174] MS14878: Prevent wallet passphrase leak in specific case --- scripts/system/marketplaces/marketplaces.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index a05778e2dd..c3edee264f 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -789,10 +789,14 @@ var selectionDisplay = null; // for gridTool.js to ignore var savedDisablePreviewOptionLocked = false; var savedDisablePreviewOption = Menu.isOptionChecked("Disable Preview");; function maybeEnableHMDPreview() { - setTabletVisibleInSecondaryCamera(true); - DesktopPreviewProvider.setPreviewDisabledReason("USER"); - Menu.setIsOptionChecked("Disable Preview", savedDisablePreviewOption); - savedDisablePreviewOptionLocked = false; + // Set a small timeout to prevent sensitive data from being shown during + // UI fade + Script.setTimeout(function () { + setTabletVisibleInSecondaryCamera(true); + DesktopPreviewProvider.setPreviewDisabledReason("USER"); + Menu.setIsOptionChecked("Disable Preview", savedDisablePreviewOption); + savedDisablePreviewOptionLocked = false; + }, 150); } // Function Name: fromQml() From c3ef6aab1c96158ea4edb67f188da9e39c2f69be Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 7 May 2018 12:51:41 -0700 Subject: [PATCH 165/174] Don't save test scripts --- libraries/script-engine/src/ScriptEngine.h | 5 +++++ libraries/script-engine/src/ScriptEngines.cpp | 15 ++++----------- libraries/script-engine/src/ScriptEngines.h | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7a9af2278c..3001666b5d 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -526,6 +526,9 @@ public: void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; } bool isUserLoaded() const { return _isUserLoaded; } + void setQuitWhenFinished(const bool quitWhenFinished) { _quitWhenFinished = quitWhenFinished; } + bool isQuitWhenFinished() const { return _quitWhenFinished; } + // NOTE - this is used by the TypedArray implementation. we need to review this for thread safety ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } @@ -768,6 +771,8 @@ protected: std::atomic _isUserLoaded { false }; bool _isReloading { false }; + std::atomic _quitWhenFinished; + ArrayBufferClass* _arrayBufferClass; AssetScriptingInterface* _assetScriptingInterface; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index d2834e8c4a..b5a7cff0ab 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -347,7 +347,8 @@ void ScriptEngines::saveScripts() { { QReadLocker lock(&_scriptEnginesHashLock); for (auto it = _scriptEnginesHash.begin(); it != _scriptEnginesHash.end(); ++it) { - if (it.value() && it.value()->isUserLoaded()) { + // Save user-loaded scripts, only if they are set to quit when finished + if (it.value() && it.value()->isUserLoaded() && !it.value()->isQuitWhenFinished()) { auto normalizedUrl = normalizeScriptURL(it.key()); list.append(normalizedUrl.toString()); } @@ -456,7 +457,7 @@ void ScriptEngines::reloadAllScripts() { } ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, - bool activateMainWindow, bool reload, bool exitWhenFinished) { + bool activateMainWindow, bool reload, bool quitWhenFinished) { if (thread() != QThread::currentThread()) { ScriptEnginePointer result { nullptr }; BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEnginePointer, result), @@ -488,6 +489,7 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i scriptEngine = ScriptEnginePointer(new ScriptEngine(_context, NO_SCRIPT, "about:" + scriptFilename.fileName())); addScriptEngine(scriptEngine); scriptEngine->setUserLoaded(isUserLoaded); + scriptEngine->setQuitWhenFinished(quitWhenFinished); if (scriptFilename.isEmpty() || !scriptUrl.isValid()) { launchScriptEngine(scriptEngine); @@ -496,11 +498,6 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); - // Shutdown Interface when script finishes, if requested - if (exitWhenFinished) { - connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::exitWhenFinished); - } - // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl, reload); } @@ -541,10 +538,6 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { emit scriptCountChanged(); } -void ScriptEngines::exitWhenFinished() { - qApp->quit(); -} - int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 6f88e8978d..51eec8ab3e 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -88,10 +88,11 @@ public: * @param {boolean} [loadScriptFromEditor=false] * @param {boolean} [activateMainWindow=false] * @param {boolean} [reload=false] + * @param {boolean} [quitWhenFinished=false] * @returns {boolean} */ Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(), - bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool exitWhenFinished = false); + bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool quitWhenFinished = false); /**jsdoc * @function ScriptDiscoveryService.stopScript @@ -266,7 +267,6 @@ protected: ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); - void exitWhenFinished(); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEnginePointer); From 2e51a66441cc89e21337b7c38774b234b094872c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 7 May 2018 13:01:18 -0700 Subject: [PATCH 166/174] Use 'standard' format for command line parameter with multiple options. --- interface/src/Application.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8ee577c282..bb04c3bf40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -744,9 +744,9 @@ extern InputPluginList getInputPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); // Parameters used for running tests from teh command line -const QString TEST_SCRIPT { "--testScript" }; -const QString TEST_QUIT_WHEN_FINISHED { "--quitWhenFinished" }; -const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; +const QString TEST_SCRIPT_COMMAND { "--testScript" }; +const QString TEST_QUIT_WHEN_FINISHED_OPTION { "quitWhenFinished" }; +const QString TEST_SNAPSHOT_LOCATION_COMMAND { "--testSnapshotLocation" }; bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { const char** constArgv = const_cast(argv); @@ -787,7 +787,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { bool inTestMode { false }; for (int i = 0; i < argc; ++i) { QString parameter(argv[i]); - if (parameter == TEST_SCRIPT) { + if (parameter == TEST_SCRIPT_COMMAND) { inTestMode = true; break; } @@ -1019,7 +1019,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { - if (args.at(i) == TEST_SCRIPT && (i + 1) < args.size()) { + if (args.at(i) == TEST_SCRIPT_COMMAND && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); // If the URL scheme is "http(s)" then use as is, else - treat it as a local file @@ -1031,10 +1031,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } // quite when finished parameter must directly follow the test script - if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED) { + if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED_OPTION) { quitWhenFinished = true; } - } else if (args.at(i) == TEST_SNAPSHOT_LOCATION) { + } else if (args.at(i) == TEST_SNAPSHOT_LOCATION_COMMAND) { // Set test snapshot location only if it is a writeable directory QString pathname(args.at(i + 1)); QFileInfo fileInfo(pathname); From fd4530e671b96d17af052ef7882fc674800a66f6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 7 May 2018 14:39:31 -0700 Subject: [PATCH 167/174] MS3128: Remove vestigal Edit menu item --- scripts/system/edit.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 6bb815a597..523582836f 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1165,17 +1165,11 @@ function setupModelMenus() { }); modelMenuAddedDelete = true; } - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entity List...", - afterItem: "Entities", - grouping: "Advanced" - }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Parent Entity to Last", - afterItem: "Entity List...", + afterItem: "Entities", grouping: "Advanced" }); @@ -1297,7 +1291,6 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Parent Entity to Last"); Menu.removeMenuItem("Edit", "Unparent Entity"); - Menu.removeMenuItem("Edit", "Entity List..."); Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); @@ -1659,8 +1652,6 @@ function handeMenuEvent(menuItem) { Window.promptTextChanged.connect(onPromptTextChanged); Window.promptAsync("URL of SVO to import", ""); } - } else if (menuItem === "Entity List...") { - entityListTool.toggleVisible(); } else if (menuItem === "Select All Entities In Box") { selectAllEtitiesInCurrentSelectionBox(false); } else if (menuItem === "Select All Entities Touching Box") { From a593209ec132ee828f454d6f505ee7ee9cc0ea38 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 7 May 2018 15:30:17 -0700 Subject: [PATCH 168/174] remove highlight when point to the sky --- .../controllers/controllerModules/farActionGrabEntity.js | 3 +++ .../controllers/controllerModules/mouseHighlightEntities.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index cc884cdbc7..66cd197abd 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -564,6 +564,9 @@ Script.include("/~/system/libraries/Xform.js"); } } else if (this.distanceRotating) { this.distanceRotate(otherFarGrabModule); + } else if (this.highlightedEntity) { + Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); + this.highlightedEntity = null; } } return this.exitIfDisabled(controllerData); diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 3180e58e2c..ac57c8691f 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -63,6 +63,9 @@ this.highlightedEntity = targetEntityID; } } + } else if (this.highlightedEntity) { + dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); + this.highlightedEntity = null; } } From eb14658bc554c58e72e40474bbb7bdc328570d83 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 8 May 2018 11:13:06 -0700 Subject: [PATCH 169/174] Per Austin's comments. --- interface/src/Application.cpp | 4 +- tools/auto-tester/src/Downloader.cpp | 5 +-- tools/auto-tester/src/Test.cpp | 54 +++++++++++++------------ tools/auto-tester/src/Test.h | 2 - tools/auto-tester/src/ui/AutoTester.cpp | 3 +- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d1db32cdd..544d767370 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1022,9 +1022,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (args.at(i) == TEST_SCRIPT_COMMAND && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); - // If the URL scheme is "http(s)" then use as is, else - treat it as a local file + // If the URL scheme is http(s) or ftp, then use as is, else - treat it as a local file // This is done so as not break previous command line scripts - if (testScriptPath.left(4) == "http") { + if (testScriptPath.left(URL_SCHEME_HTTP.length()) == URL_SCHEME_HTTP || testScriptPath.left(URL_SCHEME_FTP.length()) == URL_SCHEME_FTP) { setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath)); } else if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); diff --git a/tools/auto-tester/src/Downloader.cpp b/tools/auto-tester/src/Downloader.cpp index e66b498bd5..530a3b61bd 100644 --- a/tools/auto-tester/src/Downloader.cpp +++ b/tools/auto-tester/src/Downloader.cpp @@ -9,7 +9,7 @@ // #include "Downloader.h" -#include +#include Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { connect( @@ -24,8 +24,7 @@ Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { void Downloader::fileDownloaded(QNetworkReply* reply) { QNetworkReply::NetworkError error = reply->error(); if (error != QNetworkReply::NetworkError::NoError) { - QMessageBox messageBox; - messageBox.information(0, "Test Aborted", "Failed to download image: " + reply->errorString()); + QMessageBox::information(0, "Test Aborted", "Failed to download image: " + reply->errorString()); return; } diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index e00bc920e5..0eec03a782 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -72,7 +72,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) QImage expectedImage(expectedImagesFullFilenames[i]); if (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height()) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); exit(-1); } @@ -80,7 +80,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) try { similarityIndex = imageComparer.compareImages(resultImage, expectedImage); } catch (...) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Image not in expected format"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Image not in expected format"); exit(-1); } @@ -127,20 +127,20 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { if (!QDir().exists(testResultsFolderPath)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); exit(-1); } QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) }; if (!QDir().mkdir(failureFolderPath)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); exit(-1); } ++index; QFile descriptionFile(failureFolderPath + "/" + TEST_RESULTS_FILENAME); if (!descriptionFile.open(QIODevice::ReadWrite)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + TEST_RESULTS_FILENAME); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + TEST_RESULTS_FILENAME); exit(-1); } @@ -160,14 +160,14 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai sourceFile = testFailure._pathname + testFailure._expectedImageFilename; destinationFile = failureFolderPath + "/" + "Expected Image.jpg"; if (!QFile::copy(sourceFile, destinationFile)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); exit(-1); } sourceFile = testFailure._pathname + testFailure._actualImageFilename; destinationFile = failureFolderPath + "/" + "Actual Image.jpg"; if (!QFile::copy(sourceFile, destinationFile)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); exit(-1); } @@ -248,9 +248,9 @@ void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactive if (!isRunningFromCommandline) { if (success) { - messageBox.information(0, "Success", "All images are as expected"); + QMessageBox::information(0, "Success", "All images are as expected"); } else { - messageBox.information(0, "Failure", "One or more images are not as expected"); + QMessageBox::information(0, "Failure", "One or more images are not as expected"); } } @@ -281,7 +281,7 @@ QString Test::extractPathFromTestsDown(const QString& fullPath) { } if (i == pathParts.length()) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad testPathname"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad testPathname"); exit(-1); } @@ -350,14 +350,14 @@ void Test::createAllRecursiveScripts() { } } - messageBox.information(0, "Success", "Scripts have been created"); + QMessageBox::information(0, "Success", "Scripts have been created"); } void Test::createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode) { const QString recursiveTestsFilename("testRecursive.js"); QFile allTestsFilename(topLevelDirectory + "/" + recursiveTestsFilename); if (!allTestsFilename.open(QIODevice::WriteOnly | QIODevice::Text)) { - messageBox.critical(0, + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create \"" + recursiveTestsFilename + "\" in directory \"" + topLevelDirectory + "\"" ); @@ -366,7 +366,9 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } QTextStream textStream(&allTestsFilename); - textStream << "// This is an automatically generated file, created by auto-tester on " << __DATE__ << ", " << __TIME__ << endl << endl; + + const QString DATE_TIME_FORMAT("MMM d yyyy, h:mm"); + textStream << "// This is an automatically generated file, created by auto-tester on " << QDateTime::currentDateTime().toString(DATE_TIME_FORMAT) << endl << endl; textStream << "var autoTester = Script.require(\"https://github.com/" + githubUser + "/hifi_tests/blob/" + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl << endl; @@ -407,7 +409,7 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } if (interactiveMode && testPathnames.length() <= 0) { - messageBox.information(0, "Failure", "No \"" + TEST_FILENAME + "\" files found"); + QMessageBox::information(0, "Failure", "No \"" + TEST_FILENAME + "\" files found"); allTestsFilename.close(); return; } @@ -418,7 +420,7 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact allTestsFilename.close(); if (interactiveMode) { - messageBox.information(0, "Success", "Script has been created"); + QMessageBox::information(0, "Success", "Script has been created"); } } @@ -443,7 +445,7 @@ void Test::createTest() { QString fullCurrentFilename = imageSourceDirectory + "/" + currentFilename; if (isInSnapshotFilenameFormat("jpg", currentFilename)) { if (i >= maxImages) { - messageBox.critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); + QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); exit(-1); } QString newFilename = "ExpectedImage_" + QString::number(i - 1).rightJustified(5, '0') + ".png"; @@ -452,14 +454,14 @@ void Test::createTest() { try { copyJPGtoPNG(fullCurrentFilename, fullNewFileName); } catch (...) { - messageBox.critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nTest creation aborted"); + QMessageBox::critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nTest creation aborted"); exit(-1); } ++i; } } - messageBox.information(0, "Success", "Test images have been created"); + QMessageBox::information(0, "Success", "Test images have been created"); } ExtractedText Test::getTestScriptLines(QString testFileName) { @@ -468,7 +470,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { QFile inputFile(testFileName); inputFile.open(QIODevice::ReadOnly); if (!inputFile.isOpen()) { - messageBox.critical(0, + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to open \"" + testFileName ); @@ -598,7 +600,7 @@ void Test::createAllMDFiles() { } } - messageBox.information(0, "Success", "MD files have been created"); + QMessageBox::information(0, "Success", "MD files have been created"); } void Test::createMDFile(const QString& testDirectory) { @@ -606,7 +608,7 @@ void Test::createMDFile(const QString& testDirectory) { QString testFileName(testDirectory + "/" + TEST_FILENAME); QFileInfo testFileInfo(testFileName); if (!testFileInfo.exists()) { - messageBox.critical(0, "Error", "Could not find file: " + TEST_FILENAME); + QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); return; } @@ -615,7 +617,7 @@ void Test::createMDFile(const QString& testDirectory) { QString mdFilename(testDirectory + "/" + "test.md"); QFile mdFile(mdFilename); if (!mdFile.open(QIODevice::WriteOnly)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); exit(-1); } @@ -650,7 +652,7 @@ void Test::createMDFile(const QString& testDirectory) { mdFile.close(); - messageBox.information(0, "Success", "Test MD file " + mdFilename + " has been created"); + QMessageBox::information(0, "Success", "Test MD file " + mdFilename + " has been created"); } void Test::createTestsOutline() { @@ -663,7 +665,7 @@ void Test::createTestsOutline() { QString mdFilename(testsRootDirectory + "/" + testsOutlineFilename); QFile mdFile(mdFilename); if (!mdFile.open(QIODevice::WriteOnly)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); exit(-1); } @@ -721,7 +723,7 @@ void Test::createTestsOutline() { mdFile.close(); - messageBox.information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); + QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); } void Test::copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename) { @@ -796,7 +798,7 @@ QString Test::getExpectedImagePartialSourceDirectory(const QString& filename) { } if (i < 0) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad filename"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad filename"); exit(-1); } diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index b341c1d00f..bc28d6ad0a 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -76,8 +76,6 @@ private: const QString TEST_RESULTS_FOLDER { "TestResults" }; const QString TEST_RESULTS_FILENAME { "TestResults.txt" }; - QMessageBox messageBox; - QDir imageDirectory; MismatchWindow mismatchWindow; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 59fe5d9de2..8fd81efc1f 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -115,6 +115,5 @@ void AutoTester::saveImage(int index) { } void AutoTester::about() { - QMessageBox messageBox; - messageBox.information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); + QMessageBox::information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); } From d5bb582811dd8f73d68e06add7b4589c766b25b7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 8 May 2018 11:40:56 -0700 Subject: [PATCH 170/174] Per Austin's comments. --- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Snapshot.h | 5 ++++- tools/auto-tester/src/ui/AutoTester.cpp | 3 +-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 73ea8398e7..39fef1d742 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -90,7 +90,7 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QStr QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { // return whatever we get back from saved file for snapshot - return static_cast(savedFileForSnapshot(image, true, QString(), QString())); + return static_cast(savedFileForSnapshot(image, true)); } QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index aad63d1037..606313f3c3 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -52,7 +52,10 @@ public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); private: - static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname); + static QFile* savedFileForSnapshot(QImage& image, + bool isTemporary, + const QString& userSelectedFilename = QString(), + const QString& userSelectedPathname = QString()); }; #endif // hifi_Snapshot_h diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 8fd81efc1f..db9974a250 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -99,8 +99,7 @@ void AutoTester::saveImage(int index) { QString fullPathname = _directoryName + "/" + _filenames[index]; if (!image.save(fullPathname, 0, 100)) { - QMessageBox messageBox; - messageBox.information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); + QMessageBox::information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); ui.progressBar->setVisible(false); return; } From 7f9f9d769adfe5e96159ae1c836322dcb643acb7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 8 May 2018 15:51:52 -0700 Subject: [PATCH 171/174] Corrected bug causing Interface not to exit at end of test. --- libraries/script-engine/src/ScriptEngines.cpp | 9 +++++++++ libraries/script-engine/src/ScriptEngines.h | 1 + 2 files changed, 10 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index b5a7cff0ab..ad6e1debe9 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -498,6 +498,11 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); + // Shutdown Interface when script finishes, if requested + if (quitWhenFinished) { + connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::quitWhenFinished); + } + // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl, reload); } @@ -538,6 +543,10 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { emit scriptCountChanged(); } +void ScriptEngines::quitWhenFinished() { + qApp->quit(); +} + int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 51eec8ab3e..4d5964e462 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -267,6 +267,7 @@ protected: ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); + void quitWhenFinished(); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEnginePointer); From 44e7541888d203cd79ba2f06a079b3cdaf382ded Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 8 May 2018 15:57:27 -0700 Subject: [PATCH 172/174] Fixing the size evaluation for compressed texture and gpu::Element Type enum --- libraries/gpu/src/gpu/Format.h | 73 ++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index d4e4a89636..7a3e0a2f82 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -50,47 +50,50 @@ enum Type : uint8_t { }; // Array providing the size in bytes for a given scalar type static const int TYPE_SIZE[NUM_TYPES] = { - 4, - 4, - 4, - 2, - 2, - 2, - 1, - 1, + 4, // FLOAT + 4, // INT32 + 4, // UINT32 + 2, // HALF + 2, // INT16 + 2, // UINT16 + 1, // INT8 + 1, // UINT8 // normalized values - 4, - 4, - 2, - 2, - 1, - 1, - 4, + 4, // NINT32 + 4, // NUINT32 + 2, // NINT16 + 2, // NUINT16 + 1, // NINT8 + 1, // NUINT8 + 1, // NUINT2 + 1, // NINT2_10_10_10 - 1 + 1, // COMPRESSED }; + // Array answering the question Does this type is integer or not static const bool TYPE_IS_INTEGER[NUM_TYPES] = { - false, - true, - true, - false, - true, - true, - true, - true, + false, // FLOAT + true, // INT32 + true, // UINT32 + false, // HALF + true, // INT16 + true, // UINT16 + true, // INT8 + true, // UINT8 // Normalized values - false, - false, - false, - false, - false, - false, - false, + false, // NINT32 + false, // NUINT32 + false, // NINT16 + false, // NUINT16 + false, // NINT8 + false, // NUINT8 + false, // NUINT2 + false, // NINT2_10_10_10 - false, + false, // COMPRESSED }; // Dimension of an Element @@ -367,9 +370,9 @@ public: static const Element PART_DRAWCALL; protected: - uint8 _semantic; - uint8 _dimension : 4; - uint8 _type : 4; + uint16 _semantic : 7; + uint16 _dimension : 4; + uint16 _type : 5; }; From 540f200b99a6df817799bb9b1f29588985c939ef Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 8 May 2018 16:34:28 -0700 Subject: [PATCH 173/174] MS14937: Fix Replace button for content sets during Checkout --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 1cfbcf9075..f25282c738 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -787,7 +787,7 @@ Rectangle { } lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = function() { - Commerce.replaceContentSet(root.itemHref); + Commerce.replaceContentSet(root.itemHref, root.certificateId); lightboxPopup.visible = false; rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start(); From 06c6f5506904f964b8c77e99ca7b083e5546c468 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 9 May 2018 09:35:42 -0700 Subject: [PATCH 174/174] MS14951: Fix Snapshot hotkey sound playback --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 038180a60d..525f0f2ee7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2128,7 +2128,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return entityServerNode && !isPhysicsEnabled(); }); - _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snap.wav")); + _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snapshot/snap.wav")); QVariant testProperty = property(hifi::properties::TEST); qDebug() << testProperty;