mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 19:29:47 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
34824b793c
56 changed files with 1075 additions and 623 deletions
|
@ -28,7 +28,7 @@ android {
|
||||||
'-DSTABLE_BUILD=' + STABLE_BUILD,
|
'-DSTABLE_BUILD=' + STABLE_BUILD,
|
||||||
'-DDISABLE_QML=OFF',
|
'-DDISABLE_QML=OFF',
|
||||||
'-DDISABLE_KTX_CACHE=OFF',
|
'-DDISABLE_KTX_CACHE=OFF',
|
||||||
'-DUSE_BREAKPAD=' + (project.hasProperty("BACKTRACE_URL") && project.hasProperty("BACKTRACE_TOKEN") ? 'ON' : 'OFF');
|
'-DUSE_BREAKPAD=' + (System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_TOKEN") ? 'ON' : 'OFF');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
@ -48,8 +48,8 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
buildConfigField "String", "BACKTRACE_URL", "\"" + (project.hasProperty("BACKTRACE_URL") ? BACKTRACE_URL : '') + "\""
|
buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
|
||||||
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (project.hasProperty("BACKTRACE_TOKEN") ? BACKTRACE_TOKEN : '') + "\""
|
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
|
@ -58,8 +58,8 @@ android {
|
||||||
project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") &&
|
project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") &&
|
||||||
project.hasProperty("HIFI_ANDROID_KEY_ALIAS") &&
|
project.hasProperty("HIFI_ANDROID_KEY_ALIAS") &&
|
||||||
project.hasProperty("HIFI_ANDROID_KEY_PASSWORD")? signingConfigs.release : null
|
project.hasProperty("HIFI_ANDROID_KEY_PASSWORD")? signingConfigs.release : null
|
||||||
buildConfigField "String", "BACKTRACE_URL", "\"" + (project.hasProperty("BACKTRACE_URL") ? BACKTRACE_URL : '') + "\""
|
buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
|
||||||
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (project.hasProperty("BACKTRACE_TOKEN") ? BACKTRACE_TOKEN : '') + "\""
|
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,10 @@ android {
|
||||||
// so our merge has to depend on the external native build
|
// so our merge has to depend on the external native build
|
||||||
variant.externalNativeBuildTasks.each { task ->
|
variant.externalNativeBuildTasks.each { task ->
|
||||||
variant.mergeResources.dependsOn(task)
|
variant.mergeResources.dependsOn(task)
|
||||||
|
def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
|
||||||
|
def runDumpSymsTask = rootProject.getTasksByName("runBreakpadDumpSyms${variant.name.capitalize()}", false).first()
|
||||||
|
runDumpSymsTask.dependsOn(task)
|
||||||
|
variant.assemble.dependsOn(uploadDumpSymsTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
variant.mergeAssets.doLast {
|
variant.mergeAssets.doLast {
|
||||||
|
|
|
@ -21,6 +21,7 @@ buildscript {
|
||||||
plugins {
|
plugins {
|
||||||
id 'de.undercouch.download' version '3.3.0'
|
id 'de.undercouch.download' version '3.3.0'
|
||||||
id "cz.malohlava" version "1.0.3"
|
id "cz.malohlava" version "1.0.3"
|
||||||
|
id "io.github.http-builder-ng.http-plugin" version "0.1.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
@ -67,6 +68,7 @@ def baseFolder = new File(HIFI_ANDROID_PRECOMPILED)
|
||||||
def appDir = new File(projectDir, 'app')
|
def appDir = new File(projectDir, 'app')
|
||||||
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
|
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
|
||||||
def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
|
def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
|
||||||
|
def breakpadDumpSymsDir = new File("${appDir}/build/tmp/breakpadDumpSyms")
|
||||||
|
|
||||||
def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
|
def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
|
||||||
def qtChecksum='04599670ccca84bd2b15f6915568eb2d'
|
def qtChecksum='04599670ccca84bd2b15f6915568eb2d'
|
||||||
|
@ -151,11 +153,11 @@ def packages = [
|
||||||
checksum: '14b02795d774457a33bbc60e00a786bc'
|
checksum: '14b02795d774457a33bbc60e00a786bc'
|
||||||
],
|
],
|
||||||
breakpad: [
|
breakpad: [
|
||||||
file: 'breakpad.zip',
|
file: 'breakpad.tgz',
|
||||||
versionId: '2OwvCCZrF171wnte5T44AnjTYFhhJsGJ',
|
versionId: '8VrYXz7oyc.QBxNia0BVJOUBvrFO61jI',
|
||||||
checksum: 'a46062a3167dfedd4fb4916136e204d2',
|
checksum: 'ddcb23df336b08017042ba4786db1d9e',
|
||||||
sharedLibFolder: 'lib',
|
sharedLibFolder: 'lib',
|
||||||
includeLibs: ['libbreakpad_client.a','libbreakpad.a']
|
includeLibs: ['libbreakpad_client.a']
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -549,7 +551,93 @@ task cleanDependencies(type: Delete) {
|
||||||
delete 'app/src/main/res/values/libs.xml'
|
delete 'app/src/main/res/values/libs.xml'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def runBreakpadDumpSyms = { buildType ->
|
||||||
|
gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
|
||||||
|
|
||||||
|
def objDir = new File("${appDir}/build/intermediates/cmake/${buildType}/obj/arm64-v8a")
|
||||||
|
def stripDebugSymbol = "${appDir}/build/intermediates/transforms/stripDebugSymbol/${buildType}/0/lib/arm64-v8a/"
|
||||||
|
def outputDir = new File(breakpadDumpSymsDir, buildType)
|
||||||
|
if (!outputDir.exists()) {
|
||||||
|
outputDir.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
objDir.eachFileRecurse (FileType.FILES) { file ->
|
||||||
|
if (file.name.endsWith('.so')) {
|
||||||
|
def output = file.name + ".sym"
|
||||||
|
def cmdArgs = [
|
||||||
|
file.toString(),
|
||||||
|
stripDebugSymbol
|
||||||
|
]
|
||||||
|
def result = exec {
|
||||||
|
workingDir HIFI_ANDROID_PRECOMPILED + '/breakpad/bin'
|
||||||
|
commandLine './dump_syms'
|
||||||
|
args cmdArgs
|
||||||
|
ignoreExitValue true
|
||||||
|
standardOutput = new BufferedOutputStream(new FileOutputStream(new File(outputDir, output)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task runBreakpadDumpSymsDebug() {
|
||||||
|
doLast {
|
||||||
|
runBreakpadDumpSyms("debug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task runBreakpadDumpSymsRelease() {
|
||||||
|
doLast {
|
||||||
|
runBreakpadDumpSyms("release");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task zipDumpSymsDebug(type: Zip, dependsOn: runBreakpadDumpSymsDebug) {
|
||||||
|
from (new File(breakpadDumpSymsDir, "debug").absolutePath)
|
||||||
|
archiveName "symbols-${RELEASE_NUMBER}-debug.zip"
|
||||||
|
destinationDir(new File("${appDir}/build/tmp/"))
|
||||||
|
}
|
||||||
|
|
||||||
|
task zipDumpSymsRelease(type: Zip, dependsOn: runBreakpadDumpSymsRelease) {
|
||||||
|
from (new File(breakpadDumpSymsDir, "release").absolutePath)
|
||||||
|
archiveName "symbols-${RELEASE_NUMBER}-release.zip"
|
||||||
|
destinationDir(new File("${appDir}/build/tmp/"))
|
||||||
|
}
|
||||||
|
|
||||||
|
task uploadBreakpadDumpSymsDebug(type:io.github.httpbuilderng.http.HttpTask, dependsOn: zipDumpSymsDebug) {
|
||||||
|
onlyIf {
|
||||||
|
System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")
|
||||||
|
}
|
||||||
|
config {
|
||||||
|
request.uri = System.getenv("CMAKE_BACKTRACE_URL")
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
request.uri.path = '/post'
|
||||||
|
request.uri.query = [format: 'symbols', token: System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")]
|
||||||
|
request.body = new File("${appDir}/build/tmp/", "symbols-${RELEASE_NUMBER}-debug.zip").bytes
|
||||||
|
request.contentType = 'application/octet-stream'
|
||||||
|
response.success {
|
||||||
|
println ("${appDir}/build/tmp/symbols-${RELEASE_NUMBER}-debug.zip uploaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task uploadBreakpadDumpSymsRelease(type:io.github.httpbuilderng.http.HttpTask, dependsOn: zipDumpSymsRelease) {
|
||||||
|
onlyIf {
|
||||||
|
System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")
|
||||||
|
}
|
||||||
|
config {
|
||||||
|
request.uri = System.getenv("CMAKE_BACKTRACE_URL")
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
request.uri.path = '/post'
|
||||||
|
request.uri.query = [format: 'symbols', token: System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")]
|
||||||
|
request.body = new File("${appDir}/build/tmp/", "symbols-${RELEASE_NUMBER}-release.zip").bytes
|
||||||
|
request.contentType = 'application/octet-stream'
|
||||||
|
response.success {
|
||||||
|
println ("${appDir}/build/tmp/symbols-${RELEASE_NUMBER}-release.zip uploaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
|
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
|
||||||
// See the comment on the qtBundle task above
|
// See the comment on the qtBundle task above
|
||||||
|
|
|
@ -646,6 +646,7 @@ Item {
|
||||||
height: 40;
|
height: 40;
|
||||||
enabled: root.hasPermissionToRezThis &&
|
enabled: root.hasPermissionToRezThis &&
|
||||||
MyAvatar.skeletonModelURL !== root.itemHref &&
|
MyAvatar.skeletonModelURL !== root.itemHref &&
|
||||||
|
!root.wornEntityID &&
|
||||||
root.valid;
|
root.valid;
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
|
|
|
@ -957,7 +957,7 @@ Rectangle {
|
||||||
function updateCurrentlyWornWearables(wearables) {
|
function updateCurrentlyWornWearables(wearables) {
|
||||||
for (var i = 0; i < purchasesModel.count; i++) {
|
for (var i = 0; i < purchasesModel.count; i++) {
|
||||||
for (var j = 0; j < wearables.length; j++) {
|
for (var j = 0; j < wearables.length; j++) {
|
||||||
if (purchasesModel.get(i).itemType === "wearable" &&
|
if (purchasesModel.get(i).item_type === "wearable" &&
|
||||||
wearables[j].entityCertID === purchasesModel.get(i).certificate_id &&
|
wearables[j].entityCertID === purchasesModel.get(i).certificate_id &&
|
||||||
wearables[j].entityEdition.toString() === purchasesModel.get(i).edition_number) {
|
wearables[j].entityEdition.toString() === purchasesModel.get(i).edition_number) {
|
||||||
purchasesModel.setProperty(i, 'wornEntityID', wearables[j].entityID);
|
purchasesModel.setProperty(i, 'wornEntityID', wearables[j].entityID);
|
||||||
|
|
|
@ -253,7 +253,11 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
|
||||||
} else if (link === "#blockchain") {
|
} else if (link === "#blockchain") {
|
||||||
Qt.openUrlExternally("https://docs.highfidelity.com/high-fidelity-commerce");
|
Qt.openUrlExternally("https://docs.highfidelity.com/high-fidelity-commerce");
|
||||||
} else if (link === "#bank") {
|
} else if (link === "#bank") {
|
||||||
Qt.openUrlExternally("hifi://BankOfHighFidelity");
|
if ((Account.metaverseServerURL).toString().indexOf("staging") >= 0) {
|
||||||
|
Qt.openUrlExternally("hifi://hifiqa-master-metaverse-staging"); // So that we can test in staging.
|
||||||
|
} else {
|
||||||
|
Qt.openUrlExternally("hifi://BankOfHighFidelity");
|
||||||
|
}
|
||||||
} else if (link === "#support") {
|
} else if (link === "#support") {
|
||||||
Qt.openUrlExternally("mailto:support@highfidelity.com");
|
Qt.openUrlExternally("mailto:support@highfidelity.com");
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ Item {
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
width: parent.width/2;
|
width: parent.width/2 - anchors.leftMargin;
|
||||||
height: 80;
|
height: 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,64 +252,6 @@ Item {
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
|
||||||
Item {
|
|
||||||
// On empty history. We don't want to flash and then replace, so don't show until we know we should.
|
|
||||||
// The history is empty when it contains 1 item (the pending item count) AND there are no pending items.
|
|
||||||
visible: transactionHistoryModel.count === 1 &&
|
|
||||||
transactionHistoryModel.retrievedAtLeastOnePage &&
|
|
||||||
transactionHistoryModel.get(0).count === 0;
|
|
||||||
anchors.centerIn: parent;
|
|
||||||
width: parent.width - 12;
|
|
||||||
height: parent.height;
|
|
||||||
|
|
||||||
HifiControlsUit.Separator {
|
|
||||||
colorScheme: 1;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.top: parent.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewayRegular {
|
|
||||||
id: noActivityText;
|
|
||||||
text: "Congrats! Your wallet is all set!<br><br>" +
|
|
||||||
"<b>Where's my HFC?</b><br>" +
|
|
||||||
"High Fidelity commerce is in open beta right now. Want more HFC? Get it by meeting with a banker at " +
|
|
||||||
"<a href='#goToBank'>BankOfHighFidelity</a>!"
|
|
||||||
// Text size
|
|
||||||
size: 22;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.blueAccent;
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.topMargin: 36;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 12;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 12;
|
|
||||||
height: paintedHeight;
|
|
||||||
wrapMode: Text.WordWrap;
|
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
|
||||||
|
|
||||||
onLinkActivated: {
|
|
||||||
sendSignalToWallet({ method: "transactionHistory_goToBank" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiControlsUit.Button {
|
|
||||||
id: bankButton;
|
|
||||||
color: hifi.buttons.blue;
|
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
|
||||||
anchors.top: noActivityText.bottom;
|
|
||||||
anchors.topMargin: 30;
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter;
|
|
||||||
width: parent.width/2;
|
|
||||||
height: 50;
|
|
||||||
text: "VISIT BANK OF HIGH FIDELITY";
|
|
||||||
onClicked: {
|
|
||||||
sendSignalToWallet({ method: "transactionHistory_goToBank" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: transactionHistory;
|
id: transactionHistory;
|
||||||
|
@ -411,6 +353,64 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
// On empty history. We don't want to flash and then replace, so don't show until we know we should.
|
||||||
|
// The history is empty when it contains 1 item (the pending item count) AND there are no pending items.
|
||||||
|
visible: transactionHistoryModel.count === 1 &&
|
||||||
|
transactionHistoryModel.retrievedAtLeastOnePage &&
|
||||||
|
transactionHistoryModel.get(0).count === 0;
|
||||||
|
anchors.centerIn: parent;
|
||||||
|
width: parent.width - 12;
|
||||||
|
height: parent.height;
|
||||||
|
|
||||||
|
HifiControlsUit.Separator {
|
||||||
|
colorScheme: 1;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
RalewayRegular {
|
||||||
|
id: noActivityText;
|
||||||
|
text: "Congrats! Your wallet is all set!<br><br>" +
|
||||||
|
"<b>Where's my HFC?</b><br>" +
|
||||||
|
"High Fidelity commerce is in open beta right now. Want more HFC? Get it by meeting with a banker at " +
|
||||||
|
"<a href='#goToBank'>BankOfHighFidelity</a>!"
|
||||||
|
// Text size
|
||||||
|
size: 22;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.blueAccent;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.topMargin: 36;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 12;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 12;
|
||||||
|
height: paintedHeight;
|
||||||
|
wrapMode: Text.WordWrap;
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
|
||||||
|
onLinkActivated: {
|
||||||
|
sendSignalToWallet({ method: "transactionHistory_goToBank" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: bankButton;
|
||||||
|
color: hifi.buttons.blue;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: noActivityText.bottom;
|
||||||
|
anchors.topMargin: 30;
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
|
width: parent.width/2;
|
||||||
|
height: 50;
|
||||||
|
text: "VISIT BANK OF HIGH FIDELITY";
|
||||||
|
onClicked: {
|
||||||
|
sendSignalToWallet({ method: "transactionHistory_goToBank" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <QtAndroidExtras/QAndroidJniObject>
|
#include <QtAndroidExtras/QAndroidJniObject>
|
||||||
|
|
||||||
#include <SettingHelpers.h>
|
#include <SettingHelpers.h>
|
||||||
|
#include <BuildInfo.h>
|
||||||
|
|
||||||
google_breakpad::ExceptionHandler* gBreakpadHandler;
|
google_breakpad::ExceptionHandler* gBreakpadHandler;
|
||||||
|
|
||||||
|
@ -43,7 +44,23 @@ QString obbDir() {
|
||||||
return dataAbsPath;
|
return dataAbsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flushAnnotations() {
|
||||||
|
QSettings settings(obbDir() + "/annotations.json", JSON_FORMAT);
|
||||||
|
settings.clear();
|
||||||
|
settings.beginGroup("Annotations");
|
||||||
|
for (auto k : annotations.keys()) {
|
||||||
|
settings.setValue(k, annotations.value(k));
|
||||||
|
}
|
||||||
|
settings.endGroup();
|
||||||
|
settings.sync();
|
||||||
|
}
|
||||||
|
|
||||||
bool startCrashHandler() {
|
bool startCrashHandler() {
|
||||||
|
annotations["version"] = BuildInfo::VERSION;
|
||||||
|
annotations["build_number"] = BuildInfo::BUILD_NUMBER;
|
||||||
|
annotations["build_type"] = BuildInfo::BUILD_TYPE_STRING;
|
||||||
|
|
||||||
|
flushAnnotations();
|
||||||
|
|
||||||
gBreakpadHandler = new google_breakpad::ExceptionHandler(
|
gBreakpadHandler = new google_breakpad::ExceptionHandler(
|
||||||
google_breakpad::MinidumpDescriptor(obbDir().toStdString()),
|
google_breakpad::MinidumpDescriptor(obbDir().toStdString()),
|
||||||
|
@ -56,15 +73,7 @@ void setCrashAnnotation(std::string name, std::string value) {
|
||||||
QString qName = QString::fromStdString(name);
|
QString qName = QString::fromStdString(name);
|
||||||
QString qValue = QString::fromStdString(value);
|
QString qValue = QString::fromStdString(value);
|
||||||
annotations[qName] = qValue;
|
annotations[qName] = qValue;
|
||||||
|
flushAnnotations();
|
||||||
QSettings settings(obbDir() + "/annotations.json", JSON_FORMAT);
|
|
||||||
settings.clear();
|
|
||||||
settings.beginGroup("Annotations");
|
|
||||||
for (auto k : annotations.keys()) {
|
|
||||||
settings.setValue(k, annotations.value(k));
|
|
||||||
}
|
|
||||||
settings.endGroup();
|
|
||||||
settings.sync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,25 +11,16 @@
|
||||||
|
|
||||||
#include "SecondaryCamera.h"
|
#include "SecondaryCamera.h"
|
||||||
|
|
||||||
|
#include <RenderDeferredTask.h>
|
||||||
|
#include <RenderForwardTask.h>
|
||||||
|
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
#include <TextureCache.h>
|
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
||||||
|
|
||||||
void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
|
|
||||||
task.addJob<RenderShadowTask>("RenderShadowTask", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
|
||||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
|
||||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
|
||||||
if (!isDeferred) {
|
|
||||||
task.addJob<RenderForwardTask>("Forward", items);
|
|
||||||
} else {
|
|
||||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SecondaryCameraJob { // Changes renderContext for our framebuffer and view.
|
class SecondaryCameraJob { // Changes renderContext for our framebuffer and view.
|
||||||
public:
|
public:
|
||||||
using Config = SecondaryCameraJobConfig;
|
using Config = SecondaryCameraJobConfig;
|
||||||
|
@ -213,10 +204,10 @@ void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inp
|
||||||
const auto cachedArg = task.addJob<SecondaryCameraJob>("SecondaryCamera");
|
const auto cachedArg = task.addJob<SecondaryCameraJob>("SecondaryCamera");
|
||||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||||
if (!isDeferred) {
|
if (isDeferred) {
|
||||||
task.addJob<RenderForwardTask>("Forward", items);
|
task.addJob<RenderDeferredTask>("RenderDeferredTask", items, false);
|
||||||
} else {
|
} else {
|
||||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
task.addJob<RenderForwardTask>("Forward", items);
|
||||||
}
|
}
|
||||||
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
||||||
}
|
}
|
|
@ -12,23 +12,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifndef hifi_SecondaryCamera_h
|
#ifndef hifi_SecondaryCamera_h
|
||||||
#define hifi_SecondaryCamera_h
|
#define hifi_SecondaryCamera_h
|
||||||
|
|
||||||
#include <RenderShadowTask.h>
|
|
||||||
#include <render/RenderFetchCullSortTask.h>
|
#include <render/RenderFetchCullSortTask.h>
|
||||||
#include <RenderDeferredTask.h>
|
|
||||||
#include <RenderForwardTask.h>
|
|
||||||
#include <TextureCache.h>
|
#include <TextureCache.h>
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
class MainRenderTask {
|
|
||||||
public:
|
|
||||||
using JobModel = render::Task::Model<MainRenderTask>;
|
|
||||||
|
|
||||||
MainRenderTask() {}
|
|
||||||
|
|
||||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true);
|
|
||||||
};
|
|
||||||
|
|
||||||
class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript.
|
class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript.
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation
|
Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation
|
||||||
|
|
|
@ -186,6 +186,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
uint64_t updateExpiry = startTime + UPDATE_BUDGET;
|
uint64_t updateExpiry = startTime + UPDATE_BUDGET;
|
||||||
int numAvatarsUpdated = 0;
|
int numAvatarsUpdated = 0;
|
||||||
int numAVatarsNotUpdated = 0;
|
int numAVatarsNotUpdated = 0;
|
||||||
|
bool physicsEnabled = qApp->isPhysicsEnabled();
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
while (!sortedAvatars.empty()) {
|
while (!sortedAvatars.empty()) {
|
||||||
|
@ -202,7 +203,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
if (_shouldRender) {
|
if (_shouldRender) {
|
||||||
avatar->ensureInScene(avatar, qApp->getMain3DScene());
|
avatar->ensureInScene(avatar, qApp->getMain3DScene());
|
||||||
}
|
}
|
||||||
if (!avatar->isInPhysicsSimulation()) {
|
if (physicsEnabled && !avatar->isInPhysicsSimulation()) {
|
||||||
ShapeInfo shapeInfo;
|
ShapeInfo shapeInfo;
|
||||||
avatar->computeShapeInfo(shapeInfo);
|
avatar->computeShapeInfo(shapeInfo);
|
||||||
btCollisionShape* shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
|
btCollisionShape* shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
|
||||||
|
|
|
@ -154,6 +154,10 @@ const QUuid AvatarMotionState::getObjectID() const {
|
||||||
return _avatar->getSessionUUID();
|
return _avatar->getSessionUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString AvatarMotionState::getName() const {
|
||||||
|
return _avatar->getName();
|
||||||
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
QUuid AvatarMotionState::getSimulatorID() const {
|
QUuid AvatarMotionState::getSimulatorID() const {
|
||||||
return _avatar->getSessionUUID();
|
return _avatar->getSessionUUID();
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
|
|
||||||
virtual const QUuid getObjectID() const override;
|
virtual const QUuid getObjectID() const override;
|
||||||
|
|
||||||
|
virtual QString getName() const override;
|
||||||
virtual QUuid getSimulatorID() const override;
|
virtual QUuid getSimulatorID() const override;
|
||||||
|
|
||||||
void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal);
|
void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal);
|
||||||
|
|
|
@ -127,31 +127,40 @@ EC_KEY* readKeys(const char* filename) {
|
||||||
bool Wallet::writeBackupInstructions() {
|
bool Wallet::writeBackupInstructions() {
|
||||||
QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html");
|
QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html");
|
||||||
QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE);
|
QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE);
|
||||||
|
QFile inputFile(inputFilename);
|
||||||
QFile outputFile(outputFilename);
|
QFile outputFile(outputFilename);
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
if (QFile::exists(outputFilename) || getKeyFilePath() == "")
|
if (getKeyFilePath() == "")
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QFile::copy(inputFilename, outputFilename);
|
|
||||||
|
|
||||||
if (QFile::exists(outputFilename) && outputFile.open(QIODevice::ReadWrite)) {
|
if (QFile::exists(inputFilename) && inputFile.open(QIODevice::ReadOnly)) {
|
||||||
|
if (outputFile.open(QIODevice::ReadWrite)) {
|
||||||
|
// Read the data from the original file, then close it
|
||||||
|
QByteArray fileData = inputFile.readAll();
|
||||||
|
inputFile.close();
|
||||||
|
|
||||||
QByteArray fileData = outputFile.readAll();
|
// Translate the data from the original file into a QString
|
||||||
QString text(fileData);
|
QString text(fileData);
|
||||||
|
|
||||||
text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath());
|
// Replace the necessary string
|
||||||
|
text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath());
|
||||||
|
|
||||||
outputFile.seek(0); // go to the beginning of the file
|
// Write the new text back to the file
|
||||||
outputFile.write(text.toUtf8()); // write the new text back to the file
|
outputFile.write(text.toUtf8());
|
||||||
|
|
||||||
outputFile.close(); // close the file handle.
|
// Close the output file
|
||||||
|
outputFile.close();
|
||||||
|
|
||||||
retval = true;
|
retval = true;
|
||||||
qCDebug(commerce) << "wrote html file successfully";
|
qCDebug(commerce) << "wrote html file successfully";
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "failed to open output html file" << outputFilename;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qCDebug(commerce) << "failed to open output html file" << outputFilename;
|
qCDebug(commerce) << "failed to open input html file" << inputFilename;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,7 +307,6 @@ void Avatar::updateAvatarEntities() {
|
||||||
// NOTE: if this avatar entity is not attached to us, strip its entity script completely...
|
// NOTE: if this avatar entity is not attached to us, strip its entity script completely...
|
||||||
auto attachedScript = properties.getScript();
|
auto attachedScript = properties.getScript();
|
||||||
if (!isMyAvatar() && !attachedScript.isEmpty()) {
|
if (!isMyAvatar() && !attachedScript.isEmpty()) {
|
||||||
qCDebug(avatars_renderer) << "removing entity script from avatar attached entity:" << entityID << "old script:" << attachedScript;
|
|
||||||
QString noScript;
|
QString noScript;
|
||||||
properties.setScript(noScript);
|
properties.setScript(noScript);
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,6 +363,14 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityRenderer::updateModelTransform() {
|
||||||
|
bool success = false;
|
||||||
|
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||||
|
if (success) {
|
||||||
|
_modelTransform = newModelTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
|
void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
|
@ -419,4 +427,4 @@ void EntityRenderer::addMaterial(graphics::MaterialLayer material, const std::st
|
||||||
void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
||||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||||
_materials[parentMaterialName].remove(material);
|
_materials[parentMaterialName].remove(material);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ protected:
|
||||||
virtual void doRender(RenderArgs* args) = 0;
|
virtual void doRender(RenderArgs* args) = 0;
|
||||||
|
|
||||||
bool isFading() const { return _isFading; }
|
bool isFading() const { return _isFading; }
|
||||||
|
void updateModelTransform();
|
||||||
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||||
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
||||||
|
|
||||||
|
@ -140,6 +141,7 @@ protected:
|
||||||
bool _needsRenderUpdate { false };
|
bool _needsRenderUpdate { false };
|
||||||
// Only touched on the rendering thread
|
// Only touched on the rendering thread
|
||||||
bool _renderUpdateQueued{ false };
|
bool _renderUpdateQueued{ false };
|
||||||
|
Transform _renderTransform;
|
||||||
|
|
||||||
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
||||||
std::mutex _materialsLock;
|
std::mutex _materialsLock;
|
||||||
|
|
|
@ -35,7 +35,6 @@ private:
|
||||||
glm::vec2 _materialMappingPos;
|
glm::vec2 _materialMappingPos;
|
||||||
glm::vec2 _materialMappingScale;
|
glm::vec2 _materialMappingScale;
|
||||||
float _materialMappingRot;
|
float _materialMappingRot;
|
||||||
Transform _renderTransform;
|
|
||||||
|
|
||||||
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
||||||
};
|
};
|
||||||
|
|
|
@ -122,6 +122,14 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* key = (void*)this;
|
||||||
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
|
||||||
|
withWriteLock([&] {
|
||||||
|
updateModelTransform();
|
||||||
|
_renderTransform = getModelTransform();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
|
@ -319,7 +327,10 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
||||||
// In trail mode, the particles are created in world space.
|
// In trail mode, the particles are created in world space.
|
||||||
// so we only set a transform if they're not in trail mode
|
// so we only set a transform if they're not in trail mode
|
||||||
if (!_particleProperties.emission.shouldTrail) {
|
if (!_particleProperties.emission.shouldTrail) {
|
||||||
transform = getModelTransform();
|
|
||||||
|
withReadLock([&] {
|
||||||
|
transform = _renderTransform;
|
||||||
|
});
|
||||||
transform.setScale(vec3(1));
|
transform.setScale(vec3(1));
|
||||||
}
|
}
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
|
@ -97,16 +97,25 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
addMaterial(graphics::MaterialLayer(_material, 0), "0");
|
addMaterial(graphics::MaterialLayer(_material, 0), "0");
|
||||||
|
|
||||||
_shape = entity->getShape();
|
_shape = entity->getShape();
|
||||||
_position = entity->getWorldPosition();
|
});
|
||||||
_dimensions = entity->getScaledDimensions();
|
|
||||||
_orientation = entity->getWorldOrientation();
|
|
||||||
_renderTransform = getModelTransform();
|
|
||||||
|
|
||||||
if (_shape == entity::Sphere) {
|
void* key = (void*)this;
|
||||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
|
||||||
}
|
withWriteLock([&] {
|
||||||
|
auto entity = getEntity();
|
||||||
|
_position = entity->getWorldPosition();
|
||||||
|
_dimensions = entity->getScaledDimensions();
|
||||||
|
_orientation = entity->getWorldOrientation();
|
||||||
|
bool success = false;
|
||||||
|
auto newModelTransform = entity->getTransformToCenter(success);
|
||||||
|
_renderTransform = success ? newModelTransform : getModelTransform();
|
||||||
|
|
||||||
_renderTransform.postScale(_dimensions);
|
if (_shape == entity::Sphere) {
|
||||||
|
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderTransform.postScale(_dimensions);
|
||||||
|
});;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ private:
|
||||||
|
|
||||||
Procedural _procedural;
|
Procedural _procedural;
|
||||||
QString _lastUserData;
|
QString _lastUserData;
|
||||||
Transform _renderTransform;
|
|
||||||
entity::Shape _shape { entity::Sphere };
|
entity::Shape _shape { entity::Sphere };
|
||||||
std::shared_ptr<graphics::Material> _material;
|
std::shared_ptr<graphics::Material> _material;
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "GLMHelpers.h"
|
#include "GLMHelpers.h"
|
||||||
|
|
||||||
|
using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
|
||||||
static const int FIXED_FONT_POINT_SIZE = 40;
|
static const int FIXED_FONT_POINT_SIZE = 40;
|
||||||
|
@ -64,10 +65,20 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
|
void* key = (void*)this;
|
||||||
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_dimensions = entity->getScaledDimensions();
|
||||||
|
updateModelTransform();
|
||||||
|
_renderTransform = getModelTransform();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
_textColor = toGlm(entity->getTextColorX());
|
_textColor = toGlm(entity->getTextColorX());
|
||||||
_backgroundColor = toGlm(entity->getBackgroundColorX());
|
_backgroundColor = toGlm(entity->getBackgroundColorX());
|
||||||
_dimensions = entity->getScaledDimensions();
|
|
||||||
_faceCamera = entity->getFaceCamera();
|
_faceCamera = entity->getFaceCamera();
|
||||||
_lineHeight = entity->getLineHeight();
|
_lineHeight = entity->getLineHeight();
|
||||||
_text = entity->getText();
|
_text = entity->getText();
|
||||||
|
@ -76,24 +87,28 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
||||||
|
|
||||||
void TextEntityRenderer::doRender(RenderArgs* args) {
|
void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
||||||
|
|
||||||
|
Transform modelTransform;
|
||||||
|
glm::vec3 dimensions;
|
||||||
|
withReadLock([&] {
|
||||||
|
modelTransform = _renderTransform;
|
||||||
|
dimensions = _dimensions;
|
||||||
|
});
|
||||||
static const float SLIGHTLY_BEHIND = -0.005f;
|
static const float SLIGHTLY_BEHIND = -0.005f;
|
||||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||||
bool transparent = fadeRatio < 1.0f;
|
bool transparent = fadeRatio < 1.0f;
|
||||||
glm::vec4 textColor = glm::vec4(_textColor, fadeRatio);
|
glm::vec4 textColor = glm::vec4(_textColor, fadeRatio);
|
||||||
glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio);
|
glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio);
|
||||||
const glm::vec3& dimensions = _dimensions;
|
|
||||||
|
|
||||||
// Render background
|
// Render background
|
||||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
||||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
||||||
|
|
||||||
|
|
||||||
// Batch render calls
|
// Batch render calls
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
|
||||||
const auto& modelTransform = getModelTransform();
|
|
||||||
auto transformToTopLeft = modelTransform;
|
auto transformToTopLeft = modelTransform;
|
||||||
if (_faceCamera) {
|
if (_faceCamera) {
|
||||||
//rotate about vertical to face the camera
|
//rotate about vertical to face the camera
|
||||||
|
@ -105,7 +120,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
||||||
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
||||||
|
|
||||||
batch.setModelTransform(transformToTopLeft);
|
batch.setModelTransform(transformToTopLeft);
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
if (!_geometryID) {
|
if (!_geometryID) {
|
||||||
|
@ -113,11 +128,11 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, false);
|
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, false);
|
||||||
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
||||||
|
|
||||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
float scale = _lineHeight / _textRenderer->getFontSize();
|
||||||
transformToTopLeft.setScale(scale); // Scale to have the correct line height
|
transformToTopLeft.setScale(scale); // Scale to have the correct line height
|
||||||
batch.setModelTransform(transformToTopLeft);
|
batch.setModelTransform(transformToTopLeft);
|
||||||
|
|
||||||
float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
|
float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
|
||||||
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
|
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
|
||||||
dimensions.y - 2.0f * topMargin);
|
dimensions.y - 2.0f * topMargin);
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
~TextEntityRenderer();
|
~TextEntityRenderer();
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
|
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
int _geometryID{ 0 };
|
int _geometryID{ 0 };
|
||||||
|
@ -39,6 +40,6 @@ private:
|
||||||
float _lineHeight;
|
float _lineHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
#endif // hifi_RenderableTextEntityItem_h
|
#endif // hifi_RenderableTextEntityItem_h
|
||||||
|
|
|
@ -149,8 +149,8 @@ void WebEntityRenderer::onTimeout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
// If the content type has changed, or the old content type was QML, we need to
|
// If the content type has changed, or the old content type was QML, we need to
|
||||||
// destroy the existing surface (because surfaces don't support changing the root
|
// destroy the existing surface (because surfaces don't support changing the root
|
||||||
// object, so subsequent loads of content just overlap the existing content
|
// object, so subsequent loads of content just overlap the existing content
|
||||||
bool urlChanged = false;
|
bool urlChanged = false;
|
||||||
{
|
{
|
||||||
|
@ -187,24 +187,30 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
||||||
if (!hasWebSurface() && !buildWebSurface(entity)) {
|
if (!hasWebSurface() && !buildWebSurface(entity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urlChanged && _contentType == ContentType::HtmlContent) {
|
if (urlChanged && _contentType == ContentType::HtmlContent) {
|
||||||
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl);
|
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_contextPosition != entity->getWorldPosition()) {
|
void* key = (void*)this;
|
||||||
// update globalPosition
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
|
||||||
_contextPosition = entity->getWorldPosition();
|
withWriteLock([&] {
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
if (_contextPosition != entity->getWorldPosition()) {
|
||||||
}
|
// update globalPosition
|
||||||
|
_contextPosition = entity->getWorldPosition();
|
||||||
|
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
||||||
|
}
|
||||||
|
|
||||||
_lastDPI = entity->getDPI();
|
_lastDPI = entity->getDPI();
|
||||||
_lastLocked = entity->getLocked();
|
_lastLocked = entity->getLocked();
|
||||||
|
|
||||||
glm::vec2 windowSize = getWindowSize(entity);
|
glm::vec2 windowSize = getWindowSize(entity);
|
||||||
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
||||||
_renderTransform = getModelTransform();
|
updateModelTransform();
|
||||||
_renderTransform.postScale(entity->getScaledDimensions());
|
_renderTransform = getModelTransform();
|
||||||
|
_renderTransform.postScale(entity->getScaledDimensions());
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +303,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
|
|
||||||
if (_contentType == ContentType::HtmlContent) {
|
if (_contentType == ContentType::HtmlContent) {
|
||||||
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
||||||
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the
|
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the
|
||||||
// web entity
|
// web entity
|
||||||
if (QUrl(_lastSourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
if (QUrl(_lastSourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
||||||
_webSurface->setMaxFps(YOUTUBE_MAX_FPS);
|
_webSurface->setMaxFps(YOUTUBE_MAX_FPS);
|
||||||
|
|
|
@ -68,7 +68,6 @@ private:
|
||||||
bool _lastLocked;
|
bool _lastLocked;
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
uint64_t _lastRenderTime { 0 };
|
uint64_t _lastRenderTime { 0 };
|
||||||
Transform _renderTransform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} } // namespace
|
} } // namespace
|
||||||
|
|
|
@ -123,7 +123,6 @@ private:
|
||||||
bool _pendingSkyboxTexture{ false };
|
bool _pendingSkyboxTexture{ false };
|
||||||
|
|
||||||
QString _proceduralUserData;
|
QString _proceduralUserData;
|
||||||
Transform _renderTransform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} } // namespace
|
} } // namespace
|
||||||
|
|
|
@ -185,6 +185,7 @@ public:
|
||||||
/// Dimensions in meters (0.0 - TREE_SCALE)
|
/// Dimensions in meters (0.0 - TREE_SCALE)
|
||||||
glm::vec3 getScaledDimensions() const;
|
glm::vec3 getScaledDimensions() const;
|
||||||
virtual void setScaledDimensions(const glm::vec3& value);
|
virtual void setScaledDimensions(const glm::vec3& value);
|
||||||
|
virtual glm::vec3 getRaycastDimensions() const { return getScaledDimensions(); }
|
||||||
|
|
||||||
inline const glm::vec3 getUnscaledDimensions() const { return _unscaledDimensions; }
|
inline const glm::vec3 getUnscaledDimensions() const { return _unscaledDimensions; }
|
||||||
virtual void setUnscaledDimensions(const glm::vec3& value);
|
virtual void setUnscaledDimensions(const glm::vec3& value);
|
||||||
|
@ -239,7 +240,7 @@ public:
|
||||||
// position, size, and bounds related helpers
|
// position, size, and bounds related helpers
|
||||||
virtual AACube getMaximumAACube(bool& success) const override;
|
virtual AACube getMaximumAACube(bool& success) const override;
|
||||||
AACube getMinimumAACube(bool& success) const;
|
AACube getMinimumAACube(bool& success) const;
|
||||||
AABox getAABox(bool& success) const; /// axis aligned bounding box in world-frame (meters)
|
virtual AABox getAABox(bool& success) const; /// axis aligned bounding box in world-frame (meters)
|
||||||
|
|
||||||
using SpatiallyNestable::getQueryAACube;
|
using SpatiallyNestable::getQueryAACube;
|
||||||
virtual AACube getQueryAACube(bool& success) const override;
|
virtual AACube getQueryAACube(bool& success) const override;
|
||||||
|
|
|
@ -214,7 +214,7 @@ EntityItemID EntityTreeElement::findDetailedRayIntersection(const glm::vec3& ori
|
||||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||||
|
|
||||||
glm::vec3 dimensions = entity->getScaledDimensions();
|
glm::vec3 dimensions = entity->getRaycastDimensions();
|
||||||
glm::vec3 registrationPoint = entity->getRegistrationPoint();
|
glm::vec3 registrationPoint = entity->getRegistrationPoint();
|
||||||
glm::vec3 corner = -(dimensions * registrationPoint);
|
glm::vec3 corner = -(dimensions * registrationPoint);
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
if (!success || entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) {
|
if (!success || entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) {
|
||||||
|
|
||||||
glm::vec3 dimensions = entity->getScaledDimensions();
|
glm::vec3 dimensions = entity->getRaycastDimensions();
|
||||||
|
|
||||||
// FIXME - consider allowing the entity to determine penetration so that
|
// FIXME - consider allowing the entity to determine penetration so that
|
||||||
// entities could presumably dull actuall hull testing if they wanted to
|
// entities could presumably dull actuall hull testing if they wanted to
|
||||||
|
|
|
@ -278,6 +278,7 @@ protected:
|
||||||
|
|
||||||
struct InputStageState {
|
struct InputStageState {
|
||||||
bool _invalidFormat { true };
|
bool _invalidFormat { true };
|
||||||
|
bool _lastUpdateStereoState{ false };
|
||||||
bool _hadColorAttribute{ true };
|
bool _hadColorAttribute{ true };
|
||||||
Stream::FormatPointer _format;
|
Stream::FormatPointer _format;
|
||||||
std::string _formatKey;
|
std::string _formatKey;
|
||||||
|
|
|
@ -156,6 +156,14 @@ void GLBackend::do_setIndirectBuffer(const Batch& batch, size_t paramOffset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::updateInput() {
|
void GLBackend::updateInput() {
|
||||||
|
bool isStereoNow = isStereo();
|
||||||
|
// track stereo state change potentially happening wihtout changing the input format
|
||||||
|
// this is a rare case requesting to invalid the format
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
|
||||||
|
#endif
|
||||||
|
_input._lastUpdateStereoState = isStereoNow;
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
if (_input._invalidFormat) {
|
||||||
InputStageState::ActivationCache newActivation;
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
@ -213,7 +221,7 @@ void GLBackend::updateInput() {
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereo() ? 2 : 1));
|
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereoNow ? 2 : 1));
|
||||||
#else
|
#else
|
||||||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,6 +25,14 @@ void GL41Backend::resetInputStage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL41Backend::updateInput() {
|
void GL41Backend::updateInput() {
|
||||||
|
bool isStereoNow = isStereo();
|
||||||
|
// track stereo state change potentially happening wihtout changing the input format
|
||||||
|
// this is a rare case requesting to invalid the format
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
|
||||||
|
#endif
|
||||||
|
_input._lastUpdateStereoState = isStereoNow;
|
||||||
|
|
||||||
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
if (_input._invalidFormat) {
|
||||||
|
@ -111,7 +119,7 @@ void GL41Backend::updateInput() {
|
||||||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
||||||
}
|
}
|
||||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1));
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereoNow ? 2 : 1));
|
||||||
#else
|
#else
|
||||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,14 @@ void GL45Backend::resetInputStage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Backend::updateInput() {
|
void GL45Backend::updateInput() {
|
||||||
|
bool isStereoNow = isStereo();
|
||||||
|
// track stereo state change potentially happening wihtout changing the input format
|
||||||
|
// this is a rare case requesting to invalid the format
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
|
||||||
|
#endif
|
||||||
|
_input._lastUpdateStereoState = isStereoNow;
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
if (_input._invalidFormat) {
|
||||||
InputStageState::ActivationCache newActivation;
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
@ -84,7 +92,7 @@ void GL45Backend::updateInput() {
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereo() ? 2 : 1));
|
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereoNow ? 2 : 1));
|
||||||
#else
|
#else
|
||||||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -312,11 +312,26 @@ void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotio
|
||||||
assert(state);
|
assert(state);
|
||||||
if (state->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
if (state->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||||
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
||||||
if (!serverlessMode) {
|
|
||||||
entityState->handleDeactivation();
|
|
||||||
}
|
|
||||||
EntityItemPointer entity = entityState->getEntity();
|
EntityItemPointer entity = entityState->getEntity();
|
||||||
_entitiesToSort.insert(entity);
|
_entitiesToSort.insert(entity);
|
||||||
|
if (!serverlessMode) {
|
||||||
|
if (entity->getClientOnly()) {
|
||||||
|
switch (entityState->getOwnershipState()) {
|
||||||
|
case EntityMotionState::OwnershipState::PendingBid:
|
||||||
|
_bids.removeFirst(entityState);
|
||||||
|
entityState->clearOwnershipState();
|
||||||
|
break;
|
||||||
|
case EntityMotionState::OwnershipState::LocallyOwned:
|
||||||
|
_owned.removeFirst(entityState);
|
||||||
|
entityState->clearOwnershipState();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entityState->handleDeactivation();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,14 @@ public:
|
||||||
}
|
}
|
||||||
pop_back();
|
pop_back();
|
||||||
}
|
}
|
||||||
|
void removeFirst(EntityMotionState* state) {
|
||||||
|
for (uint32_t i = 0; i < size(); ++i) {
|
||||||
|
if ((*this)[i] == state) {
|
||||||
|
remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PhysicalEntitySimulation : public EntitySimulation {
|
class PhysicalEntitySimulation : public EntitySimulation {
|
||||||
|
|
|
@ -472,7 +472,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
const graphics::HazePointer& haze,
|
const graphics::HazePointer& haze,
|
||||||
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
||||||
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
||||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) {
|
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource,
|
||||||
|
bool renderShadows) {
|
||||||
|
|
||||||
auto args = renderContext->args;
|
auto args = renderContext->args;
|
||||||
auto& batch = (*args->_batch);
|
auto& batch = (*args->_batch);
|
||||||
|
@ -554,7 +555,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
// Check if keylight casts shadows
|
// Check if keylight casts shadows
|
||||||
bool keyLightCastShadows { false };
|
bool keyLightCastShadows { false };
|
||||||
|
|
||||||
if (lightStage && lightStage->_currentFrame._sunLights.size()) {
|
if (renderShadows && lightStage && lightStage->_currentFrame._sunLights.size()) {
|
||||||
graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front());
|
graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front());
|
||||||
if (keyLight) {
|
if (keyLight) {
|
||||||
keyLightCastShadows = keyLight->getCastShadows();
|
keyLightCastShadows = keyLight->getCastShadows();
|
||||||
|
@ -711,11 +712,6 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDeferred::RenderDeferred() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RenderDeferred::configure(const Config& config) {
|
void RenderDeferred::configure(const Config& config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +738,7 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs
|
||||||
args->_batch = &batch;
|
args->_batch = &batch;
|
||||||
_gpuTimer->begin(batch);
|
_gpuTimer->begin(batch);
|
||||||
|
|
||||||
setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, haze, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource);
|
setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, haze, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource, _renderShadows);
|
||||||
|
|
||||||
lightsJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, lightClusters);
|
lightsJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, lightClusters);
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,8 @@ public:
|
||||||
const graphics::HazePointer& haze,
|
const graphics::HazePointer& haze,
|
||||||
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
||||||
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
||||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource);
|
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource,
|
||||||
|
bool renderShadows);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderDeferredLocals {
|
class RenderDeferredLocals {
|
||||||
|
@ -166,7 +167,8 @@ public:
|
||||||
using Config = RenderDeferredConfig;
|
using Config = RenderDeferredConfig;
|
||||||
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
||||||
|
|
||||||
RenderDeferred();
|
RenderDeferred() {}
|
||||||
|
RenderDeferred(bool renderShadows) : _renderShadows(renderShadows) {}
|
||||||
|
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
|
|
||||||
|
@ -178,6 +180,9 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
gpu::RangeTimerPointer _gpuTimer;
|
gpu::RangeTimerPointer _gpuTimer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _renderShadows { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
class DefaultLightingSetup {
|
class DefaultLightingSetup {
|
||||||
|
|
|
@ -401,26 +401,34 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
||||||
glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
|
glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
|
||||||
glm::vec3 meshFrameDirection = glm::vec3(worldToMeshMatrix * glm::vec4(direction, 0.0f));
|
glm::vec3 meshFrameDirection = glm::vec3(worldToMeshMatrix * glm::vec4(direction, 0.0f));
|
||||||
|
|
||||||
for (auto& triangleSet : _modelSpaceMeshTriangleSets) {
|
int shapeID = 0;
|
||||||
float triangleSetDistance = 0.0f;
|
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||||
BoxFace triangleSetFace;
|
int partIndex = 0;
|
||||||
Triangle triangleSetTriangle;
|
for (auto &partTriangleSet : meshTriangleSets) {
|
||||||
if (triangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
|
float triangleSetDistance = 0.0f;
|
||||||
|
BoxFace triangleSetFace;
|
||||||
|
Triangle triangleSetTriangle;
|
||||||
|
if (partTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
|
||||||
|
|
||||||
glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
|
glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
|
||||||
glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
|
glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
|
||||||
float worldDistance = glm::distance(origin, worldIntersectionPoint);
|
float worldDistance = glm::distance(origin, worldIntersectionPoint);
|
||||||
|
|
||||||
if (worldDistance < bestDistance) {
|
if (worldDistance < bestDistance) {
|
||||||
bestDistance = worldDistance;
|
bestDistance = worldDistance;
|
||||||
intersectedSomething = true;
|
intersectedSomething = true;
|
||||||
face = triangleSetFace;
|
face = triangleSetFace;
|
||||||
bestModelTriangle = triangleSetTriangle;
|
bestModelTriangle = triangleSetTriangle;
|
||||||
bestWorldTriangle = triangleSetTriangle * meshToWorldMatrix;
|
bestWorldTriangle = triangleSetTriangle * meshToWorldMatrix;
|
||||||
extraInfo["worldIntersectionPoint"] = vec3toVariant(worldIntersectionPoint);
|
extraInfo["worldIntersectionPoint"] = vec3toVariant(worldIntersectionPoint);
|
||||||
extraInfo["meshIntersectionPoint"] = vec3toVariant(meshIntersectionPoint);
|
extraInfo["meshIntersectionPoint"] = vec3toVariant(meshIntersectionPoint);
|
||||||
bestSubMeshIndex = subMeshIndex;
|
extraInfo["partIndex"] = partIndex;
|
||||||
|
extraInfo["shapeID"] = shapeID;
|
||||||
|
bestSubMeshIndex = subMeshIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
partIndex++;
|
||||||
|
shapeID++;
|
||||||
}
|
}
|
||||||
subMeshIndex++;
|
subMeshIndex++;
|
||||||
}
|
}
|
||||||
|
@ -485,12 +493,14 @@ bool Model::convexHullContains(glm::vec3 point) {
|
||||||
glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
|
glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
|
||||||
glm::vec3 meshFramePoint = glm::vec3(worldToMeshMatrix * glm::vec4(point, 1.0f));
|
glm::vec3 meshFramePoint = glm::vec3(worldToMeshMatrix * glm::vec4(point, 1.0f));
|
||||||
|
|
||||||
for (const auto& triangleSet : _modelSpaceMeshTriangleSets) {
|
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||||
const AABox& box = triangleSet.getBounds();
|
for (auto &partTriangleSet : meshTriangleSets) {
|
||||||
if (box.contains(meshFramePoint)) {
|
const AABox& box = partTriangleSet.getBounds();
|
||||||
if (triangleSet.convexHullContains(meshFramePoint)) {
|
if (box.contains(meshFramePoint)) {
|
||||||
// It's inside this mesh, return true.
|
if (partTriangleSet.convexHullContains(meshFramePoint)) {
|
||||||
return true;
|
// It's inside this mesh, return true.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,9 +663,15 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
||||||
for (int i = 0; i < numberOfMeshes; i++) {
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
|
|
||||||
for (int j = 0; j < mesh.parts.size(); j++) {
|
const int numberOfParts = mesh.parts.size();
|
||||||
|
auto& meshTriangleSets = _modelSpaceMeshTriangleSets[i];
|
||||||
|
meshTriangleSets.resize(numberOfParts);
|
||||||
|
|
||||||
|
for (int j = 0; j < numberOfParts; j++) {
|
||||||
const FBXMeshPart& part = mesh.parts.at(j);
|
const FBXMeshPart& part = mesh.parts.at(j);
|
||||||
|
|
||||||
|
auto& partTriangleSet = meshTriangleSets[j];
|
||||||
|
|
||||||
const int INDICES_PER_TRIANGLE = 3;
|
const int INDICES_PER_TRIANGLE = 3;
|
||||||
const int INDICES_PER_QUAD = 4;
|
const int INDICES_PER_QUAD = 4;
|
||||||
const int TRIANGLES_PER_QUAD = 2;
|
const int TRIANGLES_PER_QUAD = 2;
|
||||||
|
@ -664,7 +680,7 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
||||||
int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD;
|
int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD;
|
||||||
int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE;
|
int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE;
|
||||||
int totalTriangles = (numberOfQuads * TRIANGLES_PER_QUAD) + numberOfTris;
|
int totalTriangles = (numberOfQuads * TRIANGLES_PER_QUAD) + numberOfTris;
|
||||||
_modelSpaceMeshTriangleSets[i].reserve(totalTriangles);
|
partTriangleSet.reserve(totalTriangles);
|
||||||
|
|
||||||
auto meshTransform = geometry.offset * mesh.modelTransform;
|
auto meshTransform = geometry.offset * mesh.modelTransform;
|
||||||
|
|
||||||
|
@ -686,8 +702,8 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
||||||
|
|
||||||
Triangle tri1 = { v0, v1, v3 };
|
Triangle tri1 = { v0, v1, v3 };
|
||||||
Triangle tri2 = { v1, v2, v3 };
|
Triangle tri2 = { v1, v2, v3 };
|
||||||
_modelSpaceMeshTriangleSets[i].insert(tri1);
|
partTriangleSet.insert(tri1);
|
||||||
_modelSpaceMeshTriangleSets[i].insert(tri2);
|
partTriangleSet.insert(tri2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,7 +722,7 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
||||||
glm::vec3 v2 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i2], 1.0f));
|
glm::vec3 v2 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i2], 1.0f));
|
||||||
|
|
||||||
Triangle tri = { v0, v1, v2 };
|
Triangle tri = { v0, v1, v2 };
|
||||||
_modelSpaceMeshTriangleSets[i].insert(tri);
|
partTriangleSet.insert(tri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -876,56 +892,58 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true);
|
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true);
|
||||||
|
|
||||||
for (const auto& triangleSet : _modelSpaceMeshTriangleSets) {
|
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||||
auto box = triangleSet.getBounds();
|
for (auto &partTriangleSet : meshTriangleSets) {
|
||||||
|
auto box = partTriangleSet.getBounds();
|
||||||
|
|
||||||
if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) {
|
if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) {
|
||||||
_debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID();
|
_debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID();
|
||||||
|
}
|
||||||
|
QVector<glm::vec3> points;
|
||||||
|
|
||||||
|
glm::vec3 brn = box.getCorner();
|
||||||
|
glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0);
|
||||||
|
glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z);
|
||||||
|
glm::vec3 blf = brn + glm::vec3(box.getDimensions().x, 0, box.getDimensions().z);
|
||||||
|
|
||||||
|
glm::vec3 trn = brn + glm::vec3(0, box.getDimensions().y, 0);
|
||||||
|
glm::vec3 tln = bln + glm::vec3(0, box.getDimensions().y, 0);
|
||||||
|
glm::vec3 trf = brf + glm::vec3(0, box.getDimensions().y, 0);
|
||||||
|
glm::vec3 tlf = blf + glm::vec3(0, box.getDimensions().y, 0);
|
||||||
|
|
||||||
|
points << brn << bln;
|
||||||
|
points << brf << blf;
|
||||||
|
points << brn << brf;
|
||||||
|
points << bln << blf;
|
||||||
|
|
||||||
|
points << trn << tln;
|
||||||
|
points << trf << tlf;
|
||||||
|
points << trn << trf;
|
||||||
|
points << tln << tlf;
|
||||||
|
|
||||||
|
points << brn << trn;
|
||||||
|
points << brf << trf;
|
||||||
|
points << bln << tln;
|
||||||
|
points << blf << tlf;
|
||||||
|
|
||||||
|
glm::vec4 color[] = {
|
||||||
|
{ 0.0f, 1.0f, 0.0f, 1.0f }, // green
|
||||||
|
{ 1.0f, 0.0f, 0.0f, 1.0f }, // red
|
||||||
|
{ 0.0f, 0.0f, 1.0f, 1.0f }, // blue
|
||||||
|
{ 1.0f, 0.0f, 1.0f, 1.0f }, // purple
|
||||||
|
{ 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
|
||||||
|
{ 0.0f, 1.0f, 1.0f, 1.0f }, // cyan
|
||||||
|
{ 1.0f, 1.0f, 1.0f, 1.0f }, // white
|
||||||
|
{ 0.0f, 0.5f, 0.0f, 1.0f },
|
||||||
|
{ 0.0f, 0.0f, 0.5f, 1.0f },
|
||||||
|
{ 0.5f, 0.0f, 0.5f, 1.0f },
|
||||||
|
{ 0.5f, 0.5f, 0.0f, 1.0f },
|
||||||
|
{ 0.0f, 0.5f, 0.5f, 1.0f } };
|
||||||
|
|
||||||
|
DependencyManager::get<GeometryCache>()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]);
|
||||||
|
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID);
|
||||||
|
colorNdx++;
|
||||||
}
|
}
|
||||||
QVector<glm::vec3> points;
|
|
||||||
|
|
||||||
glm::vec3 brn = box.getCorner();
|
|
||||||
glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0);
|
|
||||||
glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z);
|
|
||||||
glm::vec3 blf = brn + glm::vec3(box.getDimensions().x, 0, box.getDimensions().z);
|
|
||||||
|
|
||||||
glm::vec3 trn = brn + glm::vec3(0, box.getDimensions().y, 0);
|
|
||||||
glm::vec3 tln = bln + glm::vec3(0, box.getDimensions().y, 0);
|
|
||||||
glm::vec3 trf = brf + glm::vec3(0, box.getDimensions().y, 0);
|
|
||||||
glm::vec3 tlf = blf + glm::vec3(0, box.getDimensions().y, 0);
|
|
||||||
|
|
||||||
points << brn << bln;
|
|
||||||
points << brf << blf;
|
|
||||||
points << brn << brf;
|
|
||||||
points << bln << blf;
|
|
||||||
|
|
||||||
points << trn << tln;
|
|
||||||
points << trf << tlf;
|
|
||||||
points << trn << trf;
|
|
||||||
points << tln << tlf;
|
|
||||||
|
|
||||||
points << brn << trn;
|
|
||||||
points << brf << trf;
|
|
||||||
points << bln << tln;
|
|
||||||
points << blf << tlf;
|
|
||||||
|
|
||||||
glm::vec4 color[] = {
|
|
||||||
{ 0.0f, 1.0f, 0.0f, 1.0f }, // green
|
|
||||||
{ 1.0f, 0.0f, 0.0f, 1.0f }, // red
|
|
||||||
{ 0.0f, 0.0f, 1.0f, 1.0f }, // blue
|
|
||||||
{ 1.0f, 0.0f, 1.0f, 1.0f }, // purple
|
|
||||||
{ 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
|
|
||||||
{ 0.0f, 1.0f, 1.0f, 1.0f }, // cyan
|
|
||||||
{ 1.0f, 1.0f, 1.0f, 1.0f }, // white
|
|
||||||
{ 0.0f, 0.5f, 0.0f, 1.0f },
|
|
||||||
{ 0.0f, 0.0f, 0.5f, 1.0f },
|
|
||||||
{ 0.5f, 0.0f, 0.5f, 1.0f },
|
|
||||||
{ 0.5f, 0.5f, 0.0f, 1.0f },
|
|
||||||
{ 0.0f, 0.5f, 0.5f, 1.0f } };
|
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]);
|
|
||||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID);
|
|
||||||
colorNdx++;
|
|
||||||
}
|
}
|
||||||
_mutex.unlock();
|
_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,8 +423,7 @@ protected:
|
||||||
bool _overrideModelTransform { false };
|
bool _overrideModelTransform { false };
|
||||||
bool _triangleSetsValid { false };
|
bool _triangleSetsValid { false };
|
||||||
void calculateTriangleSets(const FBXGeometry& geometry);
|
void calculateTriangleSets(const FBXGeometry& geometry);
|
||||||
QVector<TriangleSet> _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes
|
std::vector<std::vector<TriangleSet>> _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes
|
||||||
|
|
||||||
|
|
||||||
virtual void createRenderItemSet();
|
virtual void createRenderItemSet();
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@ protected:
|
||||||
class DrawOverlay3D {
|
class DrawOverlay3D {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
|
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
|
||||||
|
|
||||||
using Config = DrawOverlay3DConfig;
|
using Config = DrawOverlay3DConfig;
|
||||||
using JobModel = render::Job::ModelI<DrawOverlay3D, Inputs, Config>;
|
using JobModel = render::Job::ModelI<DrawOverlay3D, Inputs, Config>;
|
||||||
|
|
||||||
|
@ -73,7 +72,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
render::ShapePlumberPointer _shapePlumber;
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
int _maxDrawn; // initialized by Config
|
int _maxDrawn; // initialized by Config
|
||||||
bool _opaquePass{ true };
|
bool _opaquePass { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
class CompositeHUD {
|
class CompositeHUD {
|
||||||
|
|
|
@ -64,8 +64,8 @@ void RenderDeferredTask::configure(const Config& config)
|
||||||
}
|
}
|
||||||
|
|
||||||
const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, const char* selectionName,
|
const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, const char* selectionName,
|
||||||
const render::Varying& metas,
|
const render::Varying& metas,
|
||||||
const render::Varying& opaques,
|
const render::Varying& opaques,
|
||||||
const render::Varying& transparents) {
|
const render::Varying& transparents) {
|
||||||
const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying();
|
const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying();
|
||||||
const auto selectedMetas = task.addJob<SelectItems>("MetaSelection", selectMetaInput, selectionName);
|
const auto selectedMetas = task.addJob<SelectItems>("MetaSelection", selectMetaInput, selectionName);
|
||||||
|
@ -75,7 +75,7 @@ const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, cons
|
||||||
return task.addJob<SelectItems>("TransparentSelection", selectItemInput, selectionName);
|
return task.addJob<SelectItems>("TransparentSelection", selectItemInput, selectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output, bool renderShadows) {
|
||||||
const auto& items = input.get<Input>();
|
const auto& items = input.get<Input>();
|
||||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
||||||
const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters, hazeModel).asVarying();
|
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters, hazeModel).asVarying();
|
||||||
|
|
||||||
task.addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs);
|
task.addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs, renderShadows);
|
||||||
|
|
||||||
|
|
||||||
// Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job
|
// Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job
|
||||||
|
|
|
@ -126,7 +126,7 @@ public:
|
||||||
RenderDeferredTask();
|
RenderDeferredTask();
|
||||||
|
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, bool renderShadows);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const render::Varying addSelectItemJobs(JobModel& task,
|
static const render::Varying addSelectItemJobs(JobModel& task,
|
||||||
|
|
|
@ -27,7 +27,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render:
|
||||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||||
|
|
||||||
if (isDeferred) {
|
if (isDeferred) {
|
||||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
task.addJob<RenderDeferredTask>("RenderDeferredTask", items, true);
|
||||||
} else {
|
} else {
|
||||||
task.addJob<RenderForwardTask>("Forward", items);
|
task.addJob<RenderForwardTask>("Forward", items);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
|
|
73
scripts/developer/tests/raypickTester.js
Normal file
73
scripts/developer/tests/raypickTester.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// raypickTester.js
|
||||||
|
//
|
||||||
|
// display intersection details (including material) when hovering over entities/avatars/overlays
|
||||||
|
//
|
||||||
|
|
||||||
|
/* eslint-disable comma-dangle, no-empty, no-magic-numbers */
|
||||||
|
|
||||||
|
var PICK_FILTERS = Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS | Picks.PICK_AVATARS | Picks.PICK_INCLUDE_NONCOLLIDABLE;
|
||||||
|
var HAND_JOINT = '_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND'.replace('RIGHT', MyAvatar.getDominantHand().toUpperCase());
|
||||||
|
var JOINT_NAME = HMD.active ? HAND_JOINT : 'Mouse';
|
||||||
|
var UPDATE_MS = 1000/30;
|
||||||
|
|
||||||
|
// create tect3d overlay to display hover results
|
||||||
|
var overlayID = Overlays.addOverlay('text3d', {
|
||||||
|
text: 'hover',
|
||||||
|
visible: false,
|
||||||
|
backgroundAlpha: 0,
|
||||||
|
isFacingAvatar: true,
|
||||||
|
lineHeight: 0.05,
|
||||||
|
dimensions: Vec3.HALF,
|
||||||
|
});
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
Overlays.deleteOverlay(overlayID);
|
||||||
|
});
|
||||||
|
|
||||||
|
// create raycast picker
|
||||||
|
var pickID = Picks.createPick(PickType.Ray, {
|
||||||
|
joint: JOINT_NAME,
|
||||||
|
filter: PICK_FILTERS,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
var blacklist = [ overlayID ]; // exclude hover text from ray pick results
|
||||||
|
Picks.setIgnoreItems(pickID, blacklist);
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
Picks.removePick(pickID);
|
||||||
|
});
|
||||||
|
|
||||||
|
// query object materials (using the Graphics.* API)
|
||||||
|
function getSubmeshMaterial(objectID, shapeID) {
|
||||||
|
try {
|
||||||
|
var materialLayers = Graphics.getModel(objectID).materialLayers;
|
||||||
|
var shapeMaterialLayers = materialLayers[shapeID];
|
||||||
|
return shapeMaterialLayers[0].material;
|
||||||
|
} catch (e) {
|
||||||
|
return { name: '<unknown>' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// refresh hover overlay text based on intersection results
|
||||||
|
function updateOverlay(overlayID, result) {
|
||||||
|
var material = this.getSubmeshMaterial(result.objectID, result.extraInfo.shapeID);
|
||||||
|
var position = Vec3.mix(result.searchRay.origin, result.intersection, 0.5);
|
||||||
|
var extraInfo = result.extraInfo;
|
||||||
|
var text = [
|
||||||
|
'mesh: ' + extraInfo.subMeshName,
|
||||||
|
'materialName: ' + material.name,
|
||||||
|
'type: ' + Entities.getNestableType(result.objectID),
|
||||||
|
'distance: ' + result.distance.toFixed(2)+'m',
|
||||||
|
['submesh: ' + extraInfo.subMeshIndex, 'part: '+extraInfo.partIndex, 'shape: '+extraInfo.shapeID].join(' | '),
|
||||||
|
].filter(Boolean).join('\n');
|
||||||
|
|
||||||
|
Overlays.editOverlay(overlayID, {
|
||||||
|
text: text,
|
||||||
|
position: position,
|
||||||
|
visible: result.intersects,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// monitor for enw results at 30fps
|
||||||
|
Script.setInterval(function() {
|
||||||
|
var result = Picks.getPrevPickResult(pickID);
|
||||||
|
updateOverlay(overlayID, result);
|
||||||
|
}, UPDATE_MS);
|
|
@ -46,7 +46,6 @@ function init() {
|
||||||
|
|
||||||
function onMuteClicked() {
|
function onMuteClicked() {
|
||||||
Audio.muted = !Audio.muted;
|
Audio.muted = !Audio.muted;
|
||||||
Menu.triggerOption("Out of Bounds Vector Access");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMutePressed() {
|
function onMutePressed() {
|
||||||
|
|
|
@ -18,10 +18,16 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
Script.include("/~/system/libraries/utils.js");
|
Script.include("/~/system/libraries/utils.js");
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
|
var MARGIN = 25;
|
||||||
|
|
||||||
function InEditMode(hand) {
|
function InEditMode(hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
this.triggerClicked = false;
|
this.triggerClicked = false;
|
||||||
this.selectedTarget = null;
|
this.selectedTarget = null;
|
||||||
|
this.reticleMinX = MARGIN;
|
||||||
|
this.reticleMaxX;
|
||||||
|
this.reticleMinY = MARGIN;
|
||||||
|
this.reticleMaxY;
|
||||||
|
|
||||||
this.parameters = makeDispatcherModuleParameters(
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
160,
|
160,
|
||||||
|
@ -47,6 +53,16 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
|
return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
|
||||||
|| (HMD.homeButtonID && objectID === HMD.homeButtonID);
|
|| (HMD.homeButtonID && objectID === HMD.homeButtonID);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.calculateNewReticlePosition = function(intersection) {
|
||||||
|
var dims = Controller.getViewportDimensions();
|
||||||
|
this.reticleMaxX = dims.x - MARGIN;
|
||||||
|
this.reticleMaxY = dims.y - MARGIN;
|
||||||
|
var point2d = HMD.overlayFromWorldPoint(intersection);
|
||||||
|
point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX));
|
||||||
|
point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY));
|
||||||
|
return point2d;
|
||||||
|
};
|
||||||
|
|
||||||
this.sendPickData = function(controllerData) {
|
this.sendPickData = function(controllerData) {
|
||||||
if (controllerData.triggerClicks[this.hand]) {
|
if (controllerData.triggerClicks[this.hand]) {
|
||||||
|
@ -72,6 +88,23 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
|
|
||||||
this.triggerClicked = true;
|
this.triggerClicked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sendPointingAtData(controllerData);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sendPointingAtData = function(controllerData) {
|
||||||
|
var rayPick = controllerData.rayPicks[this.hand];
|
||||||
|
var hudRayPick = controllerData.hudRayPicks[this.hand];
|
||||||
|
var point2d = this.calculateNewReticlePosition(hudRayPick.intersection);
|
||||||
|
var desktopWindow = Window.isPointOnDesktopWindow(point2d);
|
||||||
|
var tablet = this.pointingAtTablet(rayPick.objectID);
|
||||||
|
var rightHand = this.hand === RIGHT_HAND;
|
||||||
|
Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({
|
||||||
|
method: "pointingAt",
|
||||||
|
desktopWindow: desktopWindow,
|
||||||
|
tablet: tablet,
|
||||||
|
rightHand: rightHand
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.exitModule = function() {
|
this.exitModule = function() {
|
||||||
|
@ -104,6 +137,7 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
if (overlayLaser) {
|
if (overlayLaser) {
|
||||||
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
||||||
var target = controllerData.rayPicks[this.hand].objectID;
|
var target = controllerData.rayPicks[this.hand].objectID;
|
||||||
|
this.sendPointingAtData(controllerData);
|
||||||
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
||||||
return this.exitModule();
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,7 @@ function Grabber() {
|
||||||
|
|
||||||
this.mouseRayOverlays = Picks.createPick(PickType.Ray, {
|
this.mouseRayOverlays = Picks.createPick(PickType.Ray, {
|
||||||
joint: "Mouse",
|
joint: "Mouse",
|
||||||
filter: Picks.PICK_OVERLAYS,
|
filter: Picks.PICK_OVERLAYS | Picks.PICK_INCLUDE_NONCOLLIDABLE,
|
||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
var tabletItems = getMainTabletIDs();
|
var tabletItems = getMainTabletIDs();
|
||||||
|
@ -270,7 +270,7 @@ function Grabber() {
|
||||||
var renderStates = [{name: "grabbed", end: beacon}];
|
var renderStates = [{name: "grabbed", end: beacon}];
|
||||||
this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
|
this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
|
||||||
joint: "Mouse",
|
joint: "Mouse",
|
||||||
filter: Picks.PICK_ENTITIES,
|
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE,
|
||||||
faceAvatar: true,
|
faceAvatar: true,
|
||||||
scaleWithAvatar: true,
|
scaleWithAvatar: true,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
|
@ -2027,12 +2027,8 @@ var PropertiesTool = function (opts) {
|
||||||
} else if (data.type === "update") {
|
} else if (data.type === "update") {
|
||||||
selectionManager.saveProperties();
|
selectionManager.saveProperties();
|
||||||
if (selectionManager.selections.length > 1) {
|
if (selectionManager.selections.length > 1) {
|
||||||
properties = {
|
|
||||||
locked: data.properties.locked,
|
|
||||||
visible: data.properties.visible
|
|
||||||
};
|
|
||||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||||
Entities.editEntity(selectionManager.selections[i], properties);
|
Entities.editEntity(selectionManager.selections[i], data.properties);
|
||||||
}
|
}
|
||||||
} else if (data.properties) {
|
} else if (data.properties) {
|
||||||
if (data.properties.dynamic === false) {
|
if (data.properties.dynamic === false) {
|
||||||
|
|
|
@ -269,6 +269,9 @@ For usage and examples: colpick.com/plugin
|
||||||
},
|
},
|
||||||
// Show/hide the color picker
|
// Show/hide the color picker
|
||||||
show = function (ev) {
|
show = function (ev) {
|
||||||
|
if ($(this).attr('disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Prevent the trigger of any direct parent
|
// Prevent the trigger of any direct parent
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
var cal = $('#' + $(this).data('colpickId'));
|
var cal = $('#' + $(this).data('colpickId'));
|
||||||
|
|
|
@ -13,11 +13,12 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
/* global SPACE_LOCAL, SelectionManager */
|
/* global SelectionManager, grid, rayPlaneIntersection, rayPlaneIntersection2, pushCommandForSelections,
|
||||||
|
getMainTabletIDs, getControllerWorldLocation */
|
||||||
|
|
||||||
SPACE_LOCAL = "local";
|
var SPACE_LOCAL = "local";
|
||||||
SPACE_WORLD = "world";
|
var SPACE_WORLD = "world";
|
||||||
HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
|
var HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
|
||||||
|
|
||||||
Script.include([
|
Script.include([
|
||||||
"./controllers.js",
|
"./controllers.js",
|
||||||
|
@ -58,6 +59,14 @@ SelectionManager = (function() {
|
||||||
that.setSelections([messageParsed.entityID]);
|
that.setSelections([messageParsed.entityID]);
|
||||||
} else if (messageParsed.method === "clearSelection") {
|
} else if (messageParsed.method === "clearSelection") {
|
||||||
that.clearSelections();
|
that.clearSelections();
|
||||||
|
} else if (messageParsed.method === "pointingAt") {
|
||||||
|
if (messageParsed.rightHand) {
|
||||||
|
that.pointingAtDesktopWindowRight = messageParsed.desktopWindow;
|
||||||
|
that.pointingAtTabletRight = messageParsed.tablet;
|
||||||
|
} else {
|
||||||
|
that.pointingAtDesktopWindowLeft = messageParsed.desktopWindow;
|
||||||
|
that.pointingAtTabletLeft = messageParsed.tablet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +85,7 @@ SelectionManager = (function() {
|
||||||
outlineWidth: 3,
|
outlineWidth: 3,
|
||||||
isOutlineSmooth: true
|
isOutlineSmooth: true
|
||||||
};
|
};
|
||||||
//disabling this for now as it is causing rendering issues with the other handle overlays
|
// disabling this for now as it is causing rendering issues with the other handle overlays
|
||||||
//Selection.enableListHighlight(HIGHLIGHT_LIST_NAME, editHandleOutlineStyle);
|
//Selection.enableListHighlight(HIGHLIGHT_LIST_NAME, editHandleOutlineStyle);
|
||||||
|
|
||||||
that.savedProperties = {};
|
that.savedProperties = {};
|
||||||
|
@ -93,6 +102,11 @@ SelectionManager = (function() {
|
||||||
that.worldDimensions = Vec3.ZERO;
|
that.worldDimensions = Vec3.ZERO;
|
||||||
that.worldRegistrationPoint = Vec3.HALF;
|
that.worldRegistrationPoint = Vec3.HALF;
|
||||||
that.centerPosition = Vec3.ZERO;
|
that.centerPosition = Vec3.ZERO;
|
||||||
|
|
||||||
|
that.pointingAtDesktopWindowLeft = false;
|
||||||
|
that.pointingAtDesktopWindowRight = false;
|
||||||
|
that.pointingAtTabletLeft = false;
|
||||||
|
that.pointingAtTabletRight = false;
|
||||||
|
|
||||||
that.saveProperties = function() {
|
that.saveProperties = function() {
|
||||||
that.savedProperties = {};
|
that.savedProperties = {};
|
||||||
|
@ -179,7 +193,7 @@ SelectionManager = (function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return duplicatedEntityIDs;
|
return duplicatedEntityIDs;
|
||||||
}
|
};
|
||||||
|
|
||||||
that._update = function(selectionUpdated) {
|
that._update = function(selectionUpdated) {
|
||||||
var properties = null;
|
var properties = null;
|
||||||
|
@ -257,11 +271,12 @@ SelectionManager = (function() {
|
||||||
|
|
||||||
// Normalize degrees to be in the range (-180, 180)
|
// Normalize degrees to be in the range (-180, 180)
|
||||||
function normalizeDegrees(degrees) {
|
function normalizeDegrees(degrees) {
|
||||||
degrees = ((degrees + 180) % 360) - 180;
|
var maxDegrees = 360;
|
||||||
if (degrees <= -180) {
|
var halfMaxDegrees = maxDegrees / 2;
|
||||||
degrees += 360;
|
degrees = ((degrees + halfMaxDegrees) % maxDegrees) - halfMaxDegrees;
|
||||||
|
if (degrees <= -halfMaxDegrees) {
|
||||||
|
degrees += maxDegrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
return degrees;
|
return degrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,14 +286,14 @@ SelectionDisplay = (function() {
|
||||||
|
|
||||||
var NEGATE_VECTOR = -1;
|
var NEGATE_VECTOR = -1;
|
||||||
|
|
||||||
var COLOR_GREEN = { red:31, green:198, blue:166 };
|
var COLOR_GREEN = { red: 31, green: 198, blue: 166 };
|
||||||
var COLOR_BLUE = { red:0, green:147, blue:197 };
|
var COLOR_BLUE = { red: 0, green: 147, blue: 197 };
|
||||||
var COLOR_RED = { red:226, green:51, blue:77 };
|
var COLOR_RED = { red: 226, green: 51, blue: 77 };
|
||||||
var COLOR_HOVER = { red:227, green:227, blue:227 };
|
var COLOR_HOVER = { red: 227, green: 227, blue: 227 };
|
||||||
var COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 };
|
var COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 };
|
||||||
var COLOR_SCALE_EDGE = { red:87, green:87, blue:87 };
|
var COLOR_SCALE_EDGE = { red: 87, green: 87, blue: 87 };
|
||||||
var COLOR_SCALE_CUBE = { red:106, green:106, blue:106 };
|
var COLOR_SCALE_CUBE = { red: 106, green: 106, blue: 106 };
|
||||||
var COLOR_SCALE_CUBE_SELECTED = { red:18, green:18, blue:18 };
|
var COLOR_SCALE_CUBE_SELECTED = { red: 18, green: 18, blue: 18 };
|
||||||
|
|
||||||
var TRANSLATE_ARROW_CYLINDER_OFFSET = 0.1;
|
var TRANSLATE_ARROW_CYLINDER_OFFSET = 0.1;
|
||||||
var TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE = 0.005;
|
var TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE = 0.005;
|
||||||
|
@ -307,43 +322,41 @@ SelectionDisplay = (function() {
|
||||||
var STRETCH_PANEL_WIDTH = 0.01;
|
var STRETCH_PANEL_WIDTH = 0.01;
|
||||||
|
|
||||||
var SCALE_CUBE_OFFSET = 0.5;
|
var SCALE_CUBE_OFFSET = 0.5;
|
||||||
var SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.015;
|
var SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.0125;
|
||||||
|
|
||||||
var CLONER_OFFSET = { x:0.9, y:-0.9, z:0.9 };
|
var CLONER_OFFSET = { x: 0.9, y: -0.9, z: 0.9 };
|
||||||
|
|
||||||
var CTRL_KEY_CODE = 16777249;
|
var CTRL_KEY_CODE = 16777249;
|
||||||
|
|
||||||
var AVATAR_COLLISIONS_OPTION = "Enable Avatar Collisions";
|
|
||||||
|
|
||||||
var TRANSLATE_DIRECTION = {
|
var TRANSLATE_DIRECTION = {
|
||||||
X : 0,
|
X: 0,
|
||||||
Y : 1,
|
Y: 1,
|
||||||
Z : 2
|
Z: 2
|
||||||
}
|
};
|
||||||
|
|
||||||
var STRETCH_DIRECTION = {
|
var STRETCH_DIRECTION = {
|
||||||
X : 0,
|
X: 0,
|
||||||
Y : 1,
|
Y: 1,
|
||||||
Z : 2,
|
Z: 2,
|
||||||
ALL : 3
|
ALL: 3
|
||||||
}
|
};
|
||||||
|
|
||||||
var SCALE_DIRECTION = {
|
var SCALE_DIRECTION = {
|
||||||
LBN : 0,
|
LBN: 0,
|
||||||
RBN : 1,
|
RBN: 1,
|
||||||
LBF : 2,
|
LBF: 2,
|
||||||
RBF : 3,
|
RBF: 3,
|
||||||
LTN : 4,
|
LTN: 4,
|
||||||
RTN : 5,
|
RTN: 5,
|
||||||
LTF : 6,
|
LTF: 6,
|
||||||
RTF : 7
|
RTF: 7
|
||||||
}
|
};
|
||||||
|
|
||||||
var ROTATE_DIRECTION = {
|
var ROTATE_DIRECTION = {
|
||||||
PITCH : 0,
|
PITCH: 0,
|
||||||
YAW : 1,
|
YAW: 1,
|
||||||
ROLL : 2
|
ROLL: 2
|
||||||
}
|
};
|
||||||
|
|
||||||
var spaceMode = SPACE_LOCAL;
|
var spaceMode = SPACE_LOCAL;
|
||||||
var overlayNames = [];
|
var overlayNames = [];
|
||||||
|
@ -368,7 +381,7 @@ SelectionDisplay = (function() {
|
||||||
|
|
||||||
var ctrlPressed = false;
|
var ctrlPressed = false;
|
||||||
|
|
||||||
var handleStretchCollisionOverride = false;
|
var replaceCollisionsAfterStretch = false;
|
||||||
|
|
||||||
var handlePropertiesTranslateArrowCones = {
|
var handlePropertiesTranslateArrowCones = {
|
||||||
shape: "Cone",
|
shape: "Cone",
|
||||||
|
@ -386,16 +399,16 @@ SelectionDisplay = (function() {
|
||||||
};
|
};
|
||||||
var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
||||||
var handleTranslateXCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
var handleTranslateXCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
||||||
Overlays.editOverlay(handleTranslateXCone, { color : COLOR_RED });
|
Overlays.editOverlay(handleTranslateXCone, { color: COLOR_RED });
|
||||||
Overlays.editOverlay(handleTranslateXCylinder, { color : COLOR_RED });
|
Overlays.editOverlay(handleTranslateXCylinder, { color: COLOR_RED });
|
||||||
var handleTranslateYCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
var handleTranslateYCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
||||||
var handleTranslateYCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
var handleTranslateYCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
||||||
Overlays.editOverlay(handleTranslateYCone, { color : COLOR_GREEN });
|
Overlays.editOverlay(handleTranslateYCone, { color: COLOR_GREEN });
|
||||||
Overlays.editOverlay(handleTranslateYCylinder, { color : COLOR_GREEN });
|
Overlays.editOverlay(handleTranslateYCylinder, { color: COLOR_GREEN });
|
||||||
var handleTranslateZCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
var handleTranslateZCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
||||||
var handleTranslateZCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
var handleTranslateZCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
||||||
Overlays.editOverlay(handleTranslateZCone, { color : COLOR_BLUE });
|
Overlays.editOverlay(handleTranslateZCone, { color: COLOR_BLUE });
|
||||||
Overlays.editOverlay(handleTranslateZCylinder, { color : COLOR_BLUE });
|
Overlays.editOverlay(handleTranslateZCylinder, { color: COLOR_BLUE });
|
||||||
|
|
||||||
var handlePropertiesRotateRings = {
|
var handlePropertiesRotateRings = {
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
|
@ -411,18 +424,18 @@ SelectionDisplay = (function() {
|
||||||
};
|
};
|
||||||
var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
||||||
Overlays.editOverlay(handleRotatePitchRing, {
|
Overlays.editOverlay(handleRotatePitchRing, {
|
||||||
color : COLOR_RED,
|
color: COLOR_RED,
|
||||||
majorTickMarksColor: COLOR_RED,
|
majorTickMarksColor: COLOR_RED
|
||||||
});
|
});
|
||||||
var handleRotateYawRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
var handleRotateYawRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
||||||
Overlays.editOverlay(handleRotateYawRing, {
|
Overlays.editOverlay(handleRotateYawRing, {
|
||||||
color : COLOR_GREEN,
|
color: COLOR_GREEN,
|
||||||
majorTickMarksColor: COLOR_GREEN,
|
majorTickMarksColor: COLOR_GREEN
|
||||||
});
|
});
|
||||||
var handleRotateRollRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
var handleRotateRollRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
||||||
Overlays.editOverlay(handleRotateRollRing, {
|
Overlays.editOverlay(handleRotateRollRing, {
|
||||||
color : COLOR_BLUE,
|
color: COLOR_BLUE,
|
||||||
majorTickMarksColor: COLOR_BLUE,
|
majorTickMarksColor: COLOR_BLUE
|
||||||
});
|
});
|
||||||
|
|
||||||
var handleRotateCurrentRing = Overlays.addOverlay("circle3d", {
|
var handleRotateCurrentRing = Overlays.addOverlay("circle3d", {
|
||||||
|
@ -461,11 +474,11 @@ SelectionDisplay = (function() {
|
||||||
drawInFront: true
|
drawInFront: true
|
||||||
};
|
};
|
||||||
var handleStretchXSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
var handleStretchXSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
||||||
Overlays.editOverlay(handleStretchXSphere, { color : COLOR_RED });
|
Overlays.editOverlay(handleStretchXSphere, { color: COLOR_RED });
|
||||||
var handleStretchYSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
var handleStretchYSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
||||||
Overlays.editOverlay(handleStretchYSphere, { color : COLOR_GREEN });
|
Overlays.editOverlay(handleStretchYSphere, { color: COLOR_GREEN });
|
||||||
var handleStretchZSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
var handleStretchZSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
||||||
Overlays.editOverlay(handleStretchZSphere, { color : COLOR_BLUE });
|
Overlays.editOverlay(handleStretchZSphere, { color: COLOR_BLUE });
|
||||||
|
|
||||||
var handlePropertiesStretchPanel = {
|
var handlePropertiesStretchPanel = {
|
||||||
shape: "Quad",
|
shape: "Quad",
|
||||||
|
@ -474,13 +487,13 @@ SelectionDisplay = (function() {
|
||||||
visible: false,
|
visible: false,
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: true
|
drawInFront: true
|
||||||
}
|
};
|
||||||
var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||||
Overlays.editOverlay(handleStretchXPanel, { color : COLOR_RED });
|
Overlays.editOverlay(handleStretchXPanel, { color: COLOR_RED });
|
||||||
var handleStretchYPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
var handleStretchYPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||||
Overlays.editOverlay(handleStretchYPanel, { color : COLOR_GREEN });
|
Overlays.editOverlay(handleStretchYPanel, { color: COLOR_GREEN });
|
||||||
var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||||
Overlays.editOverlay(handleStretchZPanel, { color : COLOR_BLUE });
|
Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE });
|
||||||
|
|
||||||
var handlePropertiesScaleCubes = {
|
var handlePropertiesScaleCubes = {
|
||||||
size: 0.025,
|
size: 0.025,
|
||||||
|
@ -506,7 +519,7 @@ SelectionDisplay = (function() {
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: true,
|
drawInFront: true,
|
||||||
lineWidth: 0.2
|
lineWidth: 0.2
|
||||||
}
|
};
|
||||||
var handleScaleTREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleScaleTREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
||||||
var handleScaleTLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleScaleTLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
||||||
var handleScaleTFEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleScaleTFEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
||||||
|
@ -644,11 +657,6 @@ SelectionDisplay = (function() {
|
||||||
var activeTool = null;
|
var activeTool = null;
|
||||||
var handleTools = {};
|
var handleTools = {};
|
||||||
|
|
||||||
that.shutdown = function() {
|
|
||||||
that.restoreAvatarCollisionsFromStretch();
|
|
||||||
}
|
|
||||||
Script.scriptEnding.connect(that.shutdown);
|
|
||||||
|
|
||||||
// We get mouseMoveEvents from the handControllers, via handControllerPointer.
|
// We get mouseMoveEvents from the handControllers, via handControllerPointer.
|
||||||
// But we dont' get mousePressEvents.
|
// But we dont' get mousePressEvents.
|
||||||
that.triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click');
|
that.triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click');
|
||||||
|
@ -667,7 +675,13 @@ SelectionDisplay = (function() {
|
||||||
activeHand = (activeHand === Controller.Standard.RightHand) ?
|
activeHand = (activeHand === Controller.Standard.RightHand) ?
|
||||||
Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||||
}
|
}
|
||||||
if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)) {
|
var pointingAtDesktopWindow = (hand === Controller.Standard.RightHand &&
|
||||||
|
SelectionManager.pointingAtDesktopWindowRight) ||
|
||||||
|
(hand === Controller.Standard.LeftHand &&
|
||||||
|
SelectionManager.pointingAtDesktopWindowLeft);
|
||||||
|
var pointingAtTablet = (hand === Controller.Standard.RightHand && SelectionManager.pointingAtTabletRight) ||
|
||||||
|
(hand === Controller.Standard.LeftHand && SelectionManager.pointingAtTabletLeft);
|
||||||
|
if (pointingAtDesktopWindow || pointingAtTablet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
that.mousePressEvent({});
|
that.mousePressEvent({});
|
||||||
|
@ -773,11 +787,11 @@ SelectionDisplay = (function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.resetPreviousHandleColor = function() {
|
that.resetPreviousHandleColor = function() {
|
||||||
if (previousHandle != null) {
|
if (previousHandle !== null) {
|
||||||
Overlays.editOverlay(previousHandle, { color: previousHandleColor });
|
Overlays.editOverlay(previousHandle, { color: previousHandleColor });
|
||||||
previousHandle = null;
|
previousHandle = null;
|
||||||
}
|
}
|
||||||
if (previousHandleHelper != null) {
|
if (previousHandleHelper !== null) {
|
||||||
Overlays.editOverlay(previousHandleHelper, { color: previousHandleColor });
|
Overlays.editOverlay(previousHandleHelper, { color: previousHandleColor });
|
||||||
previousHandleHelper = null;
|
previousHandleHelper = null;
|
||||||
}
|
}
|
||||||
|
@ -874,7 +888,7 @@ SelectionDisplay = (function() {
|
||||||
Overlays.editOverlay(result.overlayID, { color: COLOR_HOVER });
|
Overlays.editOverlay(result.overlayID, { color: COLOR_HOVER });
|
||||||
previousHandle = result.overlayID;
|
previousHandle = result.overlayID;
|
||||||
previousHandleHelper = that.getHandleHelper(result.overlayID);
|
previousHandleHelper = that.getHandleHelper(result.overlayID);
|
||||||
if (previousHandleHelper != null) {
|
if (previousHandleHelper !== null) {
|
||||||
Overlays.editOverlay(previousHandleHelper, { color: COLOR_HOVER });
|
Overlays.editOverlay(previousHandleHelper, { color: COLOR_HOVER });
|
||||||
}
|
}
|
||||||
previousHandleColor = pickedColor;
|
previousHandleColor = pickedColor;
|
||||||
|
@ -932,7 +946,7 @@ SelectionDisplay = (function() {
|
||||||
ctrlPressed = false;
|
ctrlPressed = false;
|
||||||
that.updateActiveRotateRing();
|
that.updateActiveRotateRing();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Triggers notification on specific key driven events
|
// Triggers notification on specific key driven events
|
||||||
that.keyPressEvent = function(key) {
|
that.keyPressEvent = function(key) {
|
||||||
|
@ -940,7 +954,7 @@ SelectionDisplay = (function() {
|
||||||
ctrlPressed = true;
|
ctrlPressed = true;
|
||||||
that.updateActiveRotateRing();
|
that.updateActiveRotateRing();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these:
|
// NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these:
|
||||||
// Controller.mousePressEvent.connect(that.mousePressEvent);
|
// Controller.mousePressEvent.connect(that.mousePressEvent);
|
||||||
|
@ -982,6 +996,11 @@ SelectionDisplay = (function() {
|
||||||
var toCameraDistance = Vec3.length(Vec3.subtract(cameraPosition, position));
|
var toCameraDistance = Vec3.length(Vec3.subtract(cameraPosition, position));
|
||||||
return toCameraDistance;
|
return toCameraDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function usePreviousPickRay(pickRayDirection, previousPickRayDirection, normal) {
|
||||||
|
return (Vec3.dot(pickRayDirection, normal) > 0 && Vec3.dot(previousPickRayDirection, normal) < 0) ||
|
||||||
|
(Vec3.dot(pickRayDirection, normal) < 0 && Vec3.dot(previousPickRayDirection, normal) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
// @return string - The mode of the currently active tool;
|
// @return string - The mode of the currently active tool;
|
||||||
// otherwise, "UNKNOWN" if there's no active tool.
|
// otherwise, "UNKNOWN" if there's no active tool.
|
||||||
|
@ -1002,8 +1021,6 @@ SelectionDisplay = (function() {
|
||||||
lastCameraOrientation = Camera.getOrientation();
|
lastCameraOrientation = Camera.getOrientation();
|
||||||
|
|
||||||
if (event !== false) {
|
if (event !== false) {
|
||||||
pickRay = generalComputePickRay(event.x, event.y);
|
|
||||||
|
|
||||||
var wantDebug = false;
|
var wantDebug = false;
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
print("select() with EVENT...... ");
|
print("select() with EVENT...... ");
|
||||||
|
@ -1029,7 +1046,8 @@ SelectionDisplay = (function() {
|
||||||
spaceMode = newSpaceMode;
|
spaceMode = newSpaceMode;
|
||||||
that.updateHandles();
|
that.updateHandles();
|
||||||
} else if (wantDebug) {
|
} else if (wantDebug) {
|
||||||
print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " + spaceMode + " DesiredMode: " + newSpaceMode);
|
print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " +
|
||||||
|
spaceMode + " DesiredMode: " + newSpaceMode);
|
||||||
}
|
}
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
print("====== SetSpaceMode called. <========");
|
print("====== SetSpaceMode called. <========");
|
||||||
|
@ -1079,7 +1097,8 @@ SelectionDisplay = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handleTools.hasOwnProperty(toolHandle)) {
|
if (!handleTools.hasOwnProperty(toolHandle)) {
|
||||||
print("WARNING: entitySelectionTool.isActiveTool - Encountered unknown grabberToolHandle: " + toolHandle + ". Tools should be registered via addHandleTool.");
|
print("WARNING: entitySelectionTool.isActiveTool - Encountered unknown grabberToolHandle: " +
|
||||||
|
toolHandle + ". Tools should be registered via addHandleTool.");
|
||||||
// EARLY EXIT
|
// EARLY EXIT
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1109,13 +1128,14 @@ SelectionDisplay = (function() {
|
||||||
var rotationInverse = Quat.inverse(rotation);
|
var rotationInverse = Quat.inverse(rotation);
|
||||||
var toCameraDistance = getDistanceToCamera(position);
|
var toCameraDistance = getDistanceToCamera(position);
|
||||||
|
|
||||||
var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -90);
|
var rotationDegrees = 90;
|
||||||
|
var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -rotationDegrees);
|
||||||
var rotationX = Quat.multiply(rotation, localRotationX);
|
var rotationX = Quat.multiply(rotation, localRotationX);
|
||||||
worldRotationX = rotationX;
|
worldRotationX = rotationX;
|
||||||
var localRotationY = Quat.fromPitchYawRollDegrees(0, 90, 0);
|
var localRotationY = Quat.fromPitchYawRollDegrees(0, rotationDegrees, 0);
|
||||||
var rotationY = Quat.multiply(rotation, localRotationY);
|
var rotationY = Quat.multiply(rotation, localRotationY);
|
||||||
worldRotationY = rotationY;
|
worldRotationY = rotationY;
|
||||||
var localRotationZ = Quat.fromPitchYawRollDegrees(90, 0, 0);
|
var localRotationZ = Quat.fromPitchYawRollDegrees(rotationDegrees, 0, 0);
|
||||||
var rotationZ = Quat.multiply(rotation, localRotationZ);
|
var rotationZ = Quat.multiply(rotation, localRotationZ);
|
||||||
worldRotationZ = rotationZ;
|
worldRotationZ = rotationZ;
|
||||||
|
|
||||||
|
@ -1128,7 +1148,7 @@ SelectionDisplay = (function() {
|
||||||
// UPDATE ROTATION RINGS
|
// UPDATE ROTATION RINGS
|
||||||
// rotateDimension is used as the base dimension for all overlays
|
// rotateDimension is used as the base dimension for all overlays
|
||||||
var rotateDimension = Math.max(maxHandleDimension, toCameraDistance * ROTATE_RING_CAMERA_DISTANCE_MULTIPLE);
|
var rotateDimension = Math.max(maxHandleDimension, toCameraDistance * ROTATE_RING_CAMERA_DISTANCE_MULTIPLE);
|
||||||
var rotateDimensions = { x:rotateDimension, y:rotateDimension, z:rotateDimension };
|
var rotateDimensions = { x: rotateDimension, y: rotateDimension, z: rotateDimension };
|
||||||
if (!isActiveTool(handleRotatePitchRing)) {
|
if (!isActiveTool(handleRotatePitchRing)) {
|
||||||
Overlays.editOverlay(handleRotatePitchRing, {
|
Overlays.editOverlay(handleRotatePitchRing, {
|
||||||
position: position,
|
position: position,
|
||||||
|
@ -1160,16 +1180,16 @@ SelectionDisplay = (function() {
|
||||||
var arrowCylinderDimension = rotateDimension * TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE /
|
var arrowCylinderDimension = rotateDimension * TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE /
|
||||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
var arrowCylinderDimensions = {
|
var arrowCylinderDimensions = {
|
||||||
x:arrowCylinderDimension,
|
x: arrowCylinderDimension,
|
||||||
y:arrowCylinderDimension * TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE,
|
y: arrowCylinderDimension * TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE,
|
||||||
z:arrowCylinderDimension
|
z: arrowCylinderDimension
|
||||||
};
|
};
|
||||||
var arrowConeDimension = rotateDimension * TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE /
|
var arrowConeDimension = rotateDimension * TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE /
|
||||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
var arrowConeDimensions = { x:arrowConeDimension, y:arrowConeDimension, z:arrowConeDimension };
|
var arrowConeDimensions = { x: arrowConeDimension, y: arrowConeDimension, z: arrowConeDimension };
|
||||||
var arrowCylinderOffset = rotateDimension * TRANSLATE_ARROW_CYLINDER_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
var arrowCylinderOffset = rotateDimension * TRANSLATE_ARROW_CYLINDER_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
var arrowConeOffset = arrowCylinderDimensions.y * TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE;
|
var arrowConeOffset = arrowCylinderDimensions.y * TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE;
|
||||||
var cylinderXPosition = { x:arrowCylinderOffset, y:0, z:0 };
|
var cylinderXPosition = { x: arrowCylinderOffset, y: 0, z: 0 };
|
||||||
cylinderXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderXPosition));
|
cylinderXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderXPosition));
|
||||||
Overlays.editOverlay(handleTranslateXCylinder, {
|
Overlays.editOverlay(handleTranslateXCylinder, {
|
||||||
position: cylinderXPosition,
|
position: cylinderXPosition,
|
||||||
|
@ -1183,7 +1203,7 @@ SelectionDisplay = (function() {
|
||||||
rotation: rotationX,
|
rotation: rotationX,
|
||||||
dimensions: arrowConeDimensions
|
dimensions: arrowConeDimensions
|
||||||
});
|
});
|
||||||
var cylinderYPosition = { x:0, y:arrowCylinderOffset, z:0 };
|
var cylinderYPosition = { x: 0, y: arrowCylinderOffset, z: 0 };
|
||||||
cylinderYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderYPosition));
|
cylinderYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderYPosition));
|
||||||
Overlays.editOverlay(handleTranslateYCylinder, {
|
Overlays.editOverlay(handleTranslateYCylinder, {
|
||||||
position: cylinderYPosition,
|
position: cylinderYPosition,
|
||||||
|
@ -1197,7 +1217,7 @@ SelectionDisplay = (function() {
|
||||||
rotation: rotationY,
|
rotation: rotationY,
|
||||||
dimensions: arrowConeDimensions
|
dimensions: arrowConeDimensions
|
||||||
});
|
});
|
||||||
var cylinderZPosition = { x:0, y:0, z:arrowCylinderOffset };
|
var cylinderZPosition = { x: 0, y: 0, z: arrowCylinderOffset };
|
||||||
cylinderZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderZPosition));
|
cylinderZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderZPosition));
|
||||||
Overlays.editOverlay(handleTranslateZCylinder, {
|
Overlays.editOverlay(handleTranslateZCylinder, {
|
||||||
position: cylinderZPosition,
|
position: cylinderZPosition,
|
||||||
|
@ -1216,61 +1236,73 @@ SelectionDisplay = (function() {
|
||||||
var scaleCubeOffsetX = SCALE_CUBE_OFFSET * dimensions.x;
|
var scaleCubeOffsetX = SCALE_CUBE_OFFSET * dimensions.x;
|
||||||
var scaleCubeOffsetY = SCALE_CUBE_OFFSET * dimensions.y;
|
var scaleCubeOffsetY = SCALE_CUBE_OFFSET * dimensions.y;
|
||||||
var scaleCubeOffsetZ = SCALE_CUBE_OFFSET * dimensions.z;
|
var scaleCubeOffsetZ = SCALE_CUBE_OFFSET * dimensions.z;
|
||||||
var scaleCubeDimension = rotateDimension * SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE /
|
|
||||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
|
||||||
var scaleCubeDimensions = { x:scaleCubeDimension, y:scaleCubeDimension, z:scaleCubeDimension };
|
|
||||||
var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY;
|
var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY;
|
||||||
var scaleLBNCubePosition = { x:-scaleCubeOffsetX, y:-scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
var scaleLBNCubePosition = { x: -scaleCubeOffsetX, y: -scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||||
scaleLBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBNCubePosition));
|
scaleLBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBNCubePosition));
|
||||||
|
var scaleLBNCubeToCamera = getDistanceToCamera(scaleLBNCubePosition);
|
||||||
|
var scaleRBNCubePosition = { x: scaleCubeOffsetX, y: -scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||||
|
scaleRBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBNCubePosition));
|
||||||
|
var scaleRBNCubeToCamera = getDistanceToCamera(scaleRBNCubePosition);
|
||||||
|
var scaleLBFCubePosition = { x: -scaleCubeOffsetX, y: -scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||||
|
scaleLBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBFCubePosition));
|
||||||
|
var scaleLBFCubeToCamera = getDistanceToCamera(scaleLBFCubePosition);
|
||||||
|
var scaleRBFCubePosition = { x: scaleCubeOffsetX, y: -scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||||
|
scaleRBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBFCubePosition));
|
||||||
|
var scaleRBFCubeToCamera = getDistanceToCamera(scaleRBFCubePosition);
|
||||||
|
var scaleLTNCubePosition = { x: -scaleCubeOffsetX, y: scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||||
|
scaleLTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTNCubePosition));
|
||||||
|
var scaleLTNCubeToCamera = getDistanceToCamera(scaleLTNCubePosition);
|
||||||
|
var scaleRTNCubePosition = { x: scaleCubeOffsetX, y: scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||||
|
scaleRTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTNCubePosition));
|
||||||
|
var scaleRTNCubeToCamera = getDistanceToCamera(scaleRTNCubePosition);
|
||||||
|
var scaleLTFCubePosition = { x: -scaleCubeOffsetX, y: scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||||
|
scaleLTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTFCubePosition));
|
||||||
|
var scaleLTFCubeToCamera = getDistanceToCamera(scaleLTFCubePosition);
|
||||||
|
var scaleRTFCubePosition = { x: scaleCubeOffsetX, y: scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||||
|
scaleRTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTFCubePosition));
|
||||||
|
var scaleRTFCubeToCamera = getDistanceToCamera(scaleRTFCubePosition);
|
||||||
|
|
||||||
|
var scaleCubeToCamera = Math.min(scaleLBNCubeToCamera, scaleRBNCubeToCamera, scaleLBFCubeToCamera,
|
||||||
|
scaleRBFCubeToCamera, scaleLTNCubeToCamera, scaleRTNCubeToCamera,
|
||||||
|
scaleLTFCubeToCamera, scaleRTFCubeToCamera);
|
||||||
|
var scaleCubeDimension = scaleCubeToCamera * SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE;
|
||||||
|
var scaleCubeDimensions = { x: scaleCubeDimension, y: scaleCubeDimension, z: scaleCubeDimension };
|
||||||
|
|
||||||
Overlays.editOverlay(handleScaleLBNCube, {
|
Overlays.editOverlay(handleScaleLBNCube, {
|
||||||
position: scaleLBNCubePosition,
|
position: scaleLBNCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleRBNCubePosition = { x:scaleCubeOffsetX, y:-scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
|
||||||
scaleRBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBNCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleRBNCube, {
|
Overlays.editOverlay(handleScaleRBNCube, {
|
||||||
position: scaleRBNCubePosition,
|
position: scaleRBNCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleLBFCubePosition = { x:-scaleCubeOffsetX, y:-scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
|
||||||
scaleLBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBFCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleLBFCube, {
|
Overlays.editOverlay(handleScaleLBFCube, {
|
||||||
position: scaleLBFCubePosition,
|
position: scaleLBFCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleRBFCubePosition = { x:scaleCubeOffsetX, y:-scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
|
||||||
scaleRBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBFCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleRBFCube, {
|
Overlays.editOverlay(handleScaleRBFCube, {
|
||||||
position: scaleRBFCubePosition,
|
position: scaleRBFCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleLTNCubePosition = { x:-scaleCubeOffsetX, y:scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
|
||||||
scaleLTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTNCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleLTNCube, {
|
Overlays.editOverlay(handleScaleLTNCube, {
|
||||||
position: scaleLTNCubePosition,
|
position: scaleLTNCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleRTNCubePosition = { x:scaleCubeOffsetX, y:scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
|
||||||
scaleRTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTNCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleRTNCube, {
|
Overlays.editOverlay(handleScaleRTNCube, {
|
||||||
position: scaleRTNCubePosition,
|
position: scaleRTNCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleLTFCubePosition = { x:-scaleCubeOffsetX, y:scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
|
||||||
scaleLTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTFCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleLTFCube, {
|
Overlays.editOverlay(handleScaleLTFCube, {
|
||||||
position: scaleLTFCubePosition,
|
position: scaleLTFCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
dimensions: scaleCubeDimensions
|
dimensions: scaleCubeDimensions
|
||||||
});
|
});
|
||||||
var scaleRTFCubePosition = { x:scaleCubeOffsetX, y:scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
|
||||||
scaleRTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTFCubePosition));
|
|
||||||
Overlays.editOverlay(handleScaleRTFCube, {
|
Overlays.editOverlay(handleScaleRTFCube, {
|
||||||
position: scaleRTFCubePosition,
|
position: scaleRTFCubePosition,
|
||||||
rotation: scaleCubeRotation,
|
rotation: scaleCubeRotation,
|
||||||
|
@ -1294,21 +1326,21 @@ SelectionDisplay = (function() {
|
||||||
// UPDATE STRETCH SPHERES
|
// UPDATE STRETCH SPHERES
|
||||||
var stretchSphereDimension = rotateDimension * STRETCH_SPHERE_CAMERA_DISTANCE_MULTIPLE /
|
var stretchSphereDimension = rotateDimension * STRETCH_SPHERE_CAMERA_DISTANCE_MULTIPLE /
|
||||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
var stretchSphereDimensions = { x:stretchSphereDimension, y:stretchSphereDimension, z:stretchSphereDimension };
|
var stretchSphereDimensions = { x: stretchSphereDimension, y: stretchSphereDimension, z: stretchSphereDimension };
|
||||||
var stretchSphereOffset = rotateDimension * STRETCH_SPHERE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
var stretchSphereOffset = rotateDimension * STRETCH_SPHERE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
var stretchXPosition = { x:stretchSphereOffset, y:0, z:0 };
|
var stretchXPosition = { x: stretchSphereOffset, y: 0, z: 0 };
|
||||||
stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition));
|
stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition));
|
||||||
Overlays.editOverlay(handleStretchXSphere, {
|
Overlays.editOverlay(handleStretchXSphere, {
|
||||||
position: stretchXPosition,
|
position: stretchXPosition,
|
||||||
dimensions: stretchSphereDimensions
|
dimensions: stretchSphereDimensions
|
||||||
});
|
});
|
||||||
var stretchYPosition = { x:0, y:stretchSphereOffset, z:0 };
|
var stretchYPosition = { x: 0, y: stretchSphereOffset, z: 0 };
|
||||||
stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition));
|
stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition));
|
||||||
Overlays.editOverlay(handleStretchYSphere, {
|
Overlays.editOverlay(handleStretchYSphere, {
|
||||||
position: stretchYPosition,
|
position: stretchYPosition,
|
||||||
dimensions: stretchSphereDimensions
|
dimensions: stretchSphereDimensions
|
||||||
});
|
});
|
||||||
var stretchZPosition = { x:0, y:0, z:stretchSphereOffset };
|
var stretchZPosition = { x: 0, y: 0, z: stretchSphereOffset };
|
||||||
stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition));
|
stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition));
|
||||||
Overlays.editOverlay(handleStretchZSphere, {
|
Overlays.editOverlay(handleStretchZSphere, {
|
||||||
position: stretchZPosition,
|
position: stretchZPosition,
|
||||||
|
@ -1325,27 +1357,29 @@ SelectionDisplay = (function() {
|
||||||
stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH;
|
stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH;
|
||||||
stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z);
|
stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z);
|
||||||
stretchPanelXDimensions.z = tempY;
|
stretchPanelXDimensions.z = tempY;
|
||||||
var stretchPanelXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:dimensions.x / 2, y:0, z:0 }));
|
var stretchPanelXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: dimensions.x / 2, y: 0, z: 0 }));
|
||||||
Overlays.editOverlay(handleStretchXPanel, {
|
Overlays.editOverlay(handleStretchXPanel, {
|
||||||
position: stretchPanelXPosition,
|
position: stretchPanelXPosition,
|
||||||
rotation: rotationZ,
|
rotation: rotationZ,
|
||||||
dimensions: stretchPanelXDimensions
|
dimensions: stretchPanelXDimensions
|
||||||
});
|
});
|
||||||
var stretchPanelYDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRTFCubePositionRotated);
|
var stretchPanelYDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRTFCubePositionRotated);
|
||||||
|
var tempX = Math.abs(stretchPanelYDimensions.x);
|
||||||
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
||||||
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
||||||
stretchPanelYDimensions.z = Math.abs(stretchPanelYDimensions.x);
|
stretchPanelYDimensions.z = tempX;
|
||||||
var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:dimensions.y / 2, z:0 }));
|
var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: dimensions.y / 2, z: 0 }));
|
||||||
Overlays.editOverlay(handleStretchYPanel, {
|
Overlays.editOverlay(handleStretchYPanel, {
|
||||||
position: stretchPanelYPosition,
|
position: stretchPanelYPosition,
|
||||||
rotation: rotationY,
|
rotation: rotationY,
|
||||||
dimensions: stretchPanelYDimensions
|
dimensions: stretchPanelYDimensions
|
||||||
});
|
});
|
||||||
var stretchPanelZDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRBFCubePositionRotated);
|
var stretchPanelZDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRBFCubePositionRotated);
|
||||||
|
tempX = Math.abs(stretchPanelZDimensions.x);
|
||||||
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
||||||
stretchPanelZDimensions.y = Math.abs(stretchPanelZDimensions.x);
|
stretchPanelZDimensions.y = tempX;
|
||||||
stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH;
|
stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH;
|
||||||
var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:0, z:dimensions.z / 2 }));
|
var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: 0, z: dimensions.z / 2 }));
|
||||||
Overlays.editOverlay(handleStretchZPanel, {
|
Overlays.editOverlay(handleStretchZPanel, {
|
||||||
position: stretchPanelZPosition,
|
position: stretchPanelZPosition,
|
||||||
rotation: rotationX,
|
rotation: rotationX,
|
||||||
|
@ -1378,10 +1412,10 @@ SelectionDisplay = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UPDATE CLONER (CURRENTLY HIDDEN FOR NOW)
|
// UPDATE CLONER (CURRENTLY HIDDEN FOR NOW)
|
||||||
var handleClonerOffset = {
|
var handleClonerOffset = {
|
||||||
x:CLONER_OFFSET.x * dimensions.x,
|
x: CLONER_OFFSET.x * dimensions.x,
|
||||||
y:CLONER_OFFSET.y * dimensions.y,
|
y: CLONER_OFFSET.y * dimensions.y,
|
||||||
z:CLONER_OFFSET.z * dimensions.z
|
z: CLONER_OFFSET.z * dimensions.z
|
||||||
};
|
};
|
||||||
var handleClonerPos = Vec3.sum(position, Vec3.multiplyQbyV(rotation, handleClonerOffset));
|
var handleClonerPos = Vec3.sum(position, Vec3.multiplyQbyV(rotation, handleClonerOffset));
|
||||||
Overlays.editOverlay(handleCloner, {
|
Overlays.editOverlay(handleCloner, {
|
||||||
|
@ -1419,9 +1453,9 @@ SelectionDisplay = (function() {
|
||||||
!isActiveTool(handleRotateYawRing) &&
|
!isActiveTool(handleRotateYawRing) &&
|
||||||
!isActiveTool(handleRotateRollRing)));
|
!isActiveTool(handleRotateRollRing)));
|
||||||
|
|
||||||
//keep cloner always hidden for now since you can hold Alt to clone while
|
// keep cloner always hidden for now since you can hold Alt to clone while
|
||||||
//translating an entity - we may bring cloner back for HMD only later
|
// translating an entity - we may bring cloner back for HMD only later
|
||||||
//that.setHandleClonerVisible(!activeTool || isActiveTool(handleCloner));
|
// that.setHandleClonerVisible(!activeTool || isActiveTool(handleCloner));
|
||||||
|
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
print("====== Update Handles <=======");
|
print("====== Update Handles <=======");
|
||||||
|
@ -1439,8 +1473,8 @@ SelectionDisplay = (function() {
|
||||||
} else if (isActiveTool(handleRotateRollRing)) {
|
} else if (isActiveTool(handleRotateRollRing)) {
|
||||||
activeRotateRing = handleRotateRollRing;
|
activeRotateRing = handleRotateRollRing;
|
||||||
}
|
}
|
||||||
if (activeRotateRing != null) {
|
if (activeRotateRing !== null) {
|
||||||
var tickMarksAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_TICK_MARKS_ANGLE;
|
var tickMarksAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_TICK_MARKS_ANGLE;
|
||||||
Overlays.editOverlay(activeRotateRing, { majorTickMarksAngle: tickMarksAngle });
|
Overlays.editOverlay(activeRotateRing, { majorTickMarksAngle: tickMarksAngle });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1621,7 +1655,7 @@ SelectionDisplay = (function() {
|
||||||
},
|
},
|
||||||
onMove: function(event) {
|
onMove: function(event) {
|
||||||
var wantDebug = false;
|
var wantDebug = false;
|
||||||
pickRay = generalComputePickRay(event.x, event.y);
|
var pickRay = generalComputePickRay(event.x, event.y);
|
||||||
|
|
||||||
var pick = rayPlaneIntersection2(pickRay, translateXZTool.pickPlanePosition, {
|
var pick = rayPlaneIntersection2(pickRay, translateXZTool.pickPlanePosition, {
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -1687,7 +1721,8 @@ SelectionDisplay = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
constrainMajorOnly = event.isControl;
|
constrainMajorOnly = event.isControl;
|
||||||
var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(-0.5, SelectionManager.worldDimensions));
|
var negateAndHalve = -0.5;
|
||||||
|
var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(negateAndHalve, SelectionManager.worldDimensions));
|
||||||
vector = Vec3.subtract(
|
vector = Vec3.subtract(
|
||||||
grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
|
grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
|
||||||
cornerPosition);
|
cornerPosition);
|
||||||
|
@ -1733,15 +1768,16 @@ SelectionDisplay = (function() {
|
||||||
var pickNormal = null;
|
var pickNormal = null;
|
||||||
var lastPick = null;
|
var lastPick = null;
|
||||||
var projectionVector = null;
|
var projectionVector = null;
|
||||||
|
var previousPickRay = null;
|
||||||
addHandleTool(overlay, {
|
addHandleTool(overlay, {
|
||||||
mode: mode,
|
mode: mode,
|
||||||
onBegin: function(event, pickRay, pickResult) {
|
onBegin: function(event, pickRay, pickResult) {
|
||||||
if (direction === TRANSLATE_DIRECTION.X) {
|
if (direction === TRANSLATE_DIRECTION.X) {
|
||||||
pickNormal = { x:0, y:1, z:1 };
|
pickNormal = { x: 0, y: 1, z: 1 };
|
||||||
} else if (direction === TRANSLATE_DIRECTION.Y) {
|
} else if (direction === TRANSLATE_DIRECTION.Y) {
|
||||||
pickNormal = { x:1, y:0, z:1 };
|
pickNormal = { x: 1, y: 0, z: 1 };
|
||||||
} else if (direction === TRANSLATE_DIRECTION.Z) {
|
} else if (direction === TRANSLATE_DIRECTION.Z) {
|
||||||
pickNormal = { x:1, y:1, z:0 };
|
pickNormal = { x: 1, y: 1, z: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
|
var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
|
||||||
|
@ -1768,22 +1804,29 @@ SelectionDisplay = (function() {
|
||||||
} else {
|
} else {
|
||||||
duplicatedEntityIDs = null;
|
duplicatedEntityIDs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousPickRay = pickRay;
|
||||||
},
|
},
|
||||||
onEnd: function(event, reason) {
|
onEnd: function(event, reason) {
|
||||||
pushCommandForSelections(duplicatedEntityIDs);
|
pushCommandForSelections(duplicatedEntityIDs);
|
||||||
},
|
},
|
||||||
onMove: function(event) {
|
onMove: function(event) {
|
||||||
pickRay = generalComputePickRay(event.x, event.y);
|
var pickRay = generalComputePickRay(event.x, event.y);
|
||||||
|
|
||||||
|
// Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
|
||||||
|
if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickNormal)) {
|
||||||
|
pickRay = previousPickRay;
|
||||||
|
}
|
||||||
|
|
||||||
var newIntersection = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, pickNormal);
|
var newIntersection = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, pickNormal);
|
||||||
var vector = Vec3.subtract(newIntersection, lastPick);
|
var vector = Vec3.subtract(newIntersection, lastPick);
|
||||||
|
|
||||||
if (direction === TRANSLATE_DIRECTION.X) {
|
if (direction === TRANSLATE_DIRECTION.X) {
|
||||||
projectionVector = { x:1, y:0, z:0 };
|
projectionVector = { x: 1, y: 0, z: 0 };
|
||||||
} else if (direction === TRANSLATE_DIRECTION.Y) {
|
} else if (direction === TRANSLATE_DIRECTION.Y) {
|
||||||
projectionVector = { x:0, y:1, z:0 };
|
projectionVector = { x: 0, y: 1, z: 0 };
|
||||||
} else if (direction === TRANSLATE_DIRECTION.Z) {
|
} else if (direction === TRANSLATE_DIRECTION.Z) {
|
||||||
projectionVector = { x:0, y:0, z:1 };
|
projectionVector = { x: 0, y: 0, z: 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
|
var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
|
||||||
|
@ -1817,6 +1860,8 @@ SelectionDisplay = (function() {
|
||||||
var newPosition = Vec3.sum(properties.position, vector);
|
var newPosition = Vec3.sum(properties.position, vector);
|
||||||
Entities.editEntity(id, { position: newPosition });
|
Entities.editEntity(id, { position: newPosition });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousPickRay = pickRay;
|
||||||
|
|
||||||
SelectionManager._update();
|
SelectionManager._update();
|
||||||
}
|
}
|
||||||
|
@ -1832,13 +1877,6 @@ SelectionDisplay = (function() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
that.restoreAvatarCollisionsFromStretch = function() {
|
|
||||||
if (handleStretchCollisionOverride) {
|
|
||||||
Menu.setIsOptionChecked(AVATAR_COLLISIONS_OPTION, true);
|
|
||||||
handleStretchCollisionOverride = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TOOL DEFINITION: HANDLE STRETCH TOOL
|
// TOOL DEFINITION: HANDLE STRETCH TOOL
|
||||||
function makeStretchTool(stretchMode, directionEnum, directionVec, pivot, offset, stretchPanel, scaleHandle) {
|
function makeStretchTool(stretchMode, directionEnum, directionVec, pivot, offset, stretchPanel, scaleHandle) {
|
||||||
var directionFor3DStretch = directionVec;
|
var directionFor3DStretch = directionVec;
|
||||||
|
@ -1864,7 +1902,6 @@ SelectionDisplay = (function() {
|
||||||
var lastPick3D = null;
|
var lastPick3D = null;
|
||||||
var initialPosition = null;
|
var initialPosition = null;
|
||||||
var initialDimensions = null;
|
var initialDimensions = null;
|
||||||
var initialIntersection = null;
|
|
||||||
var initialProperties = null;
|
var initialProperties = null;
|
||||||
var registrationPoint = null;
|
var registrationPoint = null;
|
||||||
var deltaPivot = null;
|
var deltaPivot = null;
|
||||||
|
@ -1872,6 +1909,7 @@ SelectionDisplay = (function() {
|
||||||
var pickRayPosition = null;
|
var pickRayPosition = null;
|
||||||
var pickRayPosition3D = null;
|
var pickRayPosition3D = null;
|
||||||
var rotation = null;
|
var rotation = null;
|
||||||
|
var previousPickRay = null;
|
||||||
|
|
||||||
var onBegin = function(event, pickRay, pickResult) {
|
var onBegin = function(event, pickRay, pickResult) {
|
||||||
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
||||||
|
@ -1904,7 +1942,7 @@ SelectionDisplay = (function() {
|
||||||
var scaledOffset = Vec3.multiply(0.5, offset);
|
var scaledOffset = Vec3.multiply(0.5, offset);
|
||||||
|
|
||||||
// Offset from the registration point
|
// Offset from the registration point
|
||||||
offsetRP = Vec3.subtract(scaledOffset, centeredRP);
|
var offsetRP = Vec3.subtract(scaledOffset, centeredRP);
|
||||||
|
|
||||||
// Scaled offset in world coordinates
|
// Scaled offset in world coordinates
|
||||||
var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP);
|
var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP);
|
||||||
|
@ -1914,57 +1952,10 @@ SelectionDisplay = (function() {
|
||||||
if (directionFor3DStretch) {
|
if (directionFor3DStretch) {
|
||||||
// pivot, offset and pickPlanePosition for 3D manipulation
|
// pivot, offset and pickPlanePosition for 3D manipulation
|
||||||
var scaledPivot3D = Vec3.multiply(0.5, Vec3.multiply(1.0, directionFor3DStretch));
|
var scaledPivot3D = Vec3.multiply(0.5, Vec3.multiply(1.0, directionFor3DStretch));
|
||||||
deltaPivot3D = Vec3.subtract(centeredRP, scaledPivot3D);
|
deltaPivot3D = Vec3.subtract(centeredRP, scaledPivot3D);
|
||||||
|
|
||||||
var scaledOffsetWorld3D = vec3Mult(initialDimensions,
|
|
||||||
Vec3.subtract(Vec3.multiply(0.5, Vec3.multiply(-1.0, directionFor3DStretch)), centeredRP));
|
|
||||||
|
|
||||||
pickRayPosition3D = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
|
pickRayPosition3D = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
|
||||||
}
|
}
|
||||||
var start = null;
|
|
||||||
var end = null;
|
|
||||||
if ((numDimensions === 1) && mask.x) {
|
|
||||||
start = Vec3.multiplyQbyV(rotation, {
|
|
||||||
x: -10000,
|
|
||||||
y: 0,
|
|
||||||
z: 0
|
|
||||||
});
|
|
||||||
start = Vec3.sum(start, properties.position);
|
|
||||||
end = Vec3.multiplyQbyV(rotation, {
|
|
||||||
x: 10000,
|
|
||||||
y: 0,
|
|
||||||
z: 0
|
|
||||||
});
|
|
||||||
end = Vec3.sum(end, properties.position);
|
|
||||||
}
|
|
||||||
if ((numDimensions === 1) && mask.y) {
|
|
||||||
start = Vec3.multiplyQbyV(rotation, {
|
|
||||||
x: 0,
|
|
||||||
y: -10000,
|
|
||||||
z: 0
|
|
||||||
});
|
|
||||||
start = Vec3.sum(start, properties.position);
|
|
||||||
end = Vec3.multiplyQbyV(rotation, {
|
|
||||||
x: 0,
|
|
||||||
y: 10000,
|
|
||||||
z: 0
|
|
||||||
});
|
|
||||||
end = Vec3.sum(end, properties.position);
|
|
||||||
}
|
|
||||||
if ((numDimensions === 1) && mask.z) {
|
|
||||||
start = Vec3.multiplyQbyV(rotation, {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: -10000
|
|
||||||
});
|
|
||||||
start = Vec3.sum(start, properties.position);
|
|
||||||
end = Vec3.multiplyQbyV(rotation, {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 10000
|
|
||||||
});
|
|
||||||
end = Vec3.sum(end, properties.position);
|
|
||||||
}
|
|
||||||
if (numDimensions === 1) {
|
if (numDimensions === 1) {
|
||||||
if (mask.x === 1) {
|
if (mask.x === 1) {
|
||||||
planeNormal = {
|
planeNormal = {
|
||||||
|
@ -2035,40 +2026,49 @@ SelectionDisplay = (function() {
|
||||||
SelectionManager.saveProperties();
|
SelectionManager.saveProperties();
|
||||||
that.resetPreviousHandleColor();
|
that.resetPreviousHandleColor();
|
||||||
|
|
||||||
if (stretchPanel != null) {
|
if (stretchPanel !== null) {
|
||||||
Overlays.editOverlay(stretchPanel, { visible: true });
|
Overlays.editOverlay(stretchPanel, { visible: true });
|
||||||
}
|
}
|
||||||
if (scaleHandle != null) {
|
if (scaleHandle !== null) {
|
||||||
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE_SELECTED });
|
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE_SELECTED });
|
||||||
}
|
}
|
||||||
if (Menu.isOptionChecked(AVATAR_COLLISIONS_OPTION)) {
|
|
||||||
Menu.setIsOptionChecked(AVATAR_COLLISIONS_OPTION, false);
|
var collisionToRemove = "myAvatar";
|
||||||
handleStretchCollisionOverride = true;
|
if (properties.collidesWith.indexOf(collisionToRemove) > -1) {
|
||||||
|
var newCollidesWith = properties.collidesWith.replace(collisionToRemove, "");
|
||||||
|
Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
|
||||||
|
that.replaceCollisionsAfterStretch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousPickRay = pickRay;
|
||||||
};
|
};
|
||||||
|
|
||||||
var onEnd = function(event, reason) {
|
var onEnd = function(event, reason) {
|
||||||
if (stretchPanel != null) {
|
if (stretchPanel !== null) {
|
||||||
Overlays.editOverlay(stretchPanel, { visible: false });
|
Overlays.editOverlay(stretchPanel, { visible: false });
|
||||||
}
|
}
|
||||||
if (scaleHandle != null) {
|
if (scaleHandle !== null) {
|
||||||
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE });
|
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE });
|
||||||
}
|
}
|
||||||
that.restoreAvatarCollisionsFromStretch();
|
|
||||||
|
if (that.replaceCollisionsAfterStretch) {
|
||||||
|
var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith;
|
||||||
|
Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
|
||||||
|
that.replaceCollisionsAfterStretch = false;
|
||||||
|
}
|
||||||
|
|
||||||
pushCommandForSelections();
|
pushCommandForSelections();
|
||||||
};
|
};
|
||||||
|
|
||||||
var onMove = function(event) {
|
var onMove = function(event) {
|
||||||
var proportional = (spaceMode === SPACE_WORLD) || directionEnum === STRETCH_DIRECTION.ALL;
|
var proportional = (spaceMode === SPACE_WORLD) || directionEnum === STRETCH_DIRECTION.ALL;
|
||||||
|
|
||||||
var position, dimensions, rotation;
|
var position, rotation;
|
||||||
if (spaceMode === SPACE_LOCAL) {
|
if (spaceMode === SPACE_LOCAL) {
|
||||||
position = SelectionManager.localPosition;
|
position = SelectionManager.localPosition;
|
||||||
dimensions = SelectionManager.localDimensions;
|
|
||||||
rotation = SelectionManager.localRotation;
|
rotation = SelectionManager.localRotation;
|
||||||
} else {
|
} else {
|
||||||
position = SelectionManager.worldPosition;
|
position = SelectionManager.worldPosition;
|
||||||
dimensions = SelectionManager.worldDimensions;
|
|
||||||
rotation = SelectionManager.worldRotation;
|
rotation = SelectionManager.worldRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2076,9 +2076,15 @@ SelectionDisplay = (function() {
|
||||||
var localSigns = signs;
|
var localSigns = signs;
|
||||||
var pickRay = generalComputePickRay(event.x, event.y);
|
var pickRay = generalComputePickRay(event.x, event.y);
|
||||||
|
|
||||||
|
// Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
|
||||||
|
if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, planeNormal)) {
|
||||||
|
pickRay = previousPickRay;
|
||||||
|
}
|
||||||
|
|
||||||
// Are we using handControllers or Mouse - only relevant for 3D tools
|
// Are we using handControllers or Mouse - only relevant for 3D tools
|
||||||
var controllerPose = getControllerWorldLocation(activeHand, true);
|
var controllerPose = getControllerWorldLocation(activeHand, true);
|
||||||
var vector = null;
|
var vector = null;
|
||||||
|
var newPick = null;
|
||||||
if (HMD.isHMDAvailable() && HMD.isHandControllerAvailable() &&
|
if (HMD.isHMDAvailable() && HMD.isHandControllerAvailable() &&
|
||||||
controllerPose.valid && that.triggered && directionFor3DStretch) {
|
controllerPose.valid && that.triggered && directionFor3DStretch) {
|
||||||
localDeltaPivot = deltaPivot3D;
|
localDeltaPivot = deltaPivot3D;
|
||||||
|
@ -2129,23 +2135,30 @@ SelectionDisplay = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var minimumDimension = directionEnum === STRETCH_DIRECTION.ALL ? STRETCH_ALL_MINIMUM_DIMENSION :
|
var minimumDimension = directionEnum === STRETCH_DIRECTION.ALL ? STRETCH_ALL_MINIMUM_DIMENSION :
|
||||||
STRETCH_MINIMUM_DIMENSION;
|
STRETCH_MINIMUM_DIMENSION;
|
||||||
newDimensions.x = Math.max(newDimensions.x, minimumDimension);
|
if (newDimensions.x < minimumDimension) {
|
||||||
newDimensions.y = Math.max(newDimensions.y, minimumDimension);
|
newDimensions.x = minimumDimension;
|
||||||
newDimensions.z = Math.max(newDimensions.z, minimumDimension);
|
changeInDimensions.x = minimumDimension - initialDimensions.x;
|
||||||
|
}
|
||||||
|
if (newDimensions.y < minimumDimension) {
|
||||||
|
newDimensions.y = minimumDimension;
|
||||||
|
changeInDimensions.y = minimumDimension - initialDimensions.y;
|
||||||
|
}
|
||||||
|
if (newDimensions.z < minimumDimension) {
|
||||||
|
newDimensions.z = minimumDimension;
|
||||||
|
changeInDimensions.z = minimumDimension - initialDimensions.z;
|
||||||
|
}
|
||||||
|
|
||||||
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions));
|
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions));
|
||||||
if (directionEnum === STRETCH_DIRECTION.ALL) {
|
if (directionEnum === STRETCH_DIRECTION.ALL) {
|
||||||
changeInPosition = { x:0, y:0, z:0 };
|
changeInPosition = { x: 0, y: 0, z: 0 };
|
||||||
}
|
}
|
||||||
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
||||||
|
|
||||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
Entities.editEntity(SelectionManager.selections[0], {
|
||||||
Entities.editEntity(SelectionManager.selections[i], {
|
position: newPosition,
|
||||||
position: newPosition,
|
dimensions: newDimensions
|
||||||
dimensions: newDimensions
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var wantDebug = false;
|
var wantDebug = false;
|
||||||
if (wantDebug) {
|
if (wantDebug) {
|
||||||
|
@ -2156,6 +2169,8 @@ SelectionDisplay = (function() {
|
||||||
Vec3.print(" changeInPosition:", changeInPosition);
|
Vec3.print(" changeInPosition:", changeInPosition);
|
||||||
Vec3.print(" newPosition:", newPosition);
|
Vec3.print(" newPosition:", newPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousPickRay = pickRay;
|
||||||
|
|
||||||
SelectionManager._update();
|
SelectionManager._update();
|
||||||
};// End of onMove def
|
};// End of onMove def
|
||||||
|
@ -2172,13 +2187,13 @@ SelectionDisplay = (function() {
|
||||||
var directionVector, offset, stretchPanel;
|
var directionVector, offset, stretchPanel;
|
||||||
if (directionEnum === STRETCH_DIRECTION.X) {
|
if (directionEnum === STRETCH_DIRECTION.X) {
|
||||||
stretchPanel = handleStretchXPanel;
|
stretchPanel = handleStretchXPanel;
|
||||||
directionVector = { x:-1, y:0, z:0 };
|
directionVector = { x: -1, y: 0, z: 0 };
|
||||||
} else if (directionEnum === STRETCH_DIRECTION.Y) {
|
} else if (directionEnum === STRETCH_DIRECTION.Y) {
|
||||||
stretchPanel = handleStretchYPanel;
|
stretchPanel = handleStretchYPanel;
|
||||||
directionVector = { x:0, y:-1, z:0 };
|
directionVector = { x: 0, y: -1, z: 0 };
|
||||||
} else if (directionEnum === STRETCH_DIRECTION.Z) {
|
} else if (directionEnum === STRETCH_DIRECTION.Z) {
|
||||||
stretchPanel = handleStretchZPanel
|
stretchPanel = handleStretchZPanel;
|
||||||
directionVector = { x:0, y:0, z:-1 };
|
directionVector = { x: 0, y: 0, z: -1 };
|
||||||
}
|
}
|
||||||
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
||||||
var tool = makeStretchTool(mode, directionEnum, directionVector, directionVector, offset, stretchPanel, null);
|
var tool = makeStretchTool(mode, directionEnum, directionVector, directionVector, offset, stretchPanel, null);
|
||||||
|
@ -2189,28 +2204,28 @@ SelectionDisplay = (function() {
|
||||||
function addHandleScaleTool(overlay, mode, directionEnum) {
|
function addHandleScaleTool(overlay, mode, directionEnum) {
|
||||||
var directionVector, offset, selectedHandle;
|
var directionVector, offset, selectedHandle;
|
||||||
if (directionEnum === SCALE_DIRECTION.LBN) {
|
if (directionEnum === SCALE_DIRECTION.LBN) {
|
||||||
directionVector = { x:1, y:1, z:1 };
|
directionVector = { x: 1, y: 1, z: 1 };
|
||||||
selectedHandle = handleScaleLBNCube;
|
selectedHandle = handleScaleLBNCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RBN) {
|
} else if (directionEnum === SCALE_DIRECTION.RBN) {
|
||||||
directionVector = { x:-1, y:1, z:1 };
|
directionVector = { x: -1, y: 1, z: 1 };
|
||||||
selectedHandle = handleScaleRBNCube;
|
selectedHandle = handleScaleRBNCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.LBF) {
|
} else if (directionEnum === SCALE_DIRECTION.LBF) {
|
||||||
directionVector = { x:1, y:1, z:-1 };
|
directionVector = { x: 1, y: 1, z: -1 };
|
||||||
selectedHandle = handleScaleLBFCube;
|
selectedHandle = handleScaleLBFCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RBF) {
|
} else if (directionEnum === SCALE_DIRECTION.RBF) {
|
||||||
directionVector = { x:-1, y:1, z:-1 };
|
directionVector = { x: -1, y: 1, z: -1 };
|
||||||
selectedHandle = handleScaleRBFCube;
|
selectedHandle = handleScaleRBFCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.LTN) {
|
} else if (directionEnum === SCALE_DIRECTION.LTN) {
|
||||||
directionVector = { x:1, y:-1, z:1 };
|
directionVector = { x: 1, y: -1, z: 1 };
|
||||||
selectedHandle = handleScaleLTNCube;
|
selectedHandle = handleScaleLTNCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RTN) {
|
} else if (directionEnum === SCALE_DIRECTION.RTN) {
|
||||||
directionVector = { x:-1, y:-1, z:1 };
|
directionVector = { x: -1, y: -1, z: 1 };
|
||||||
selectedHandle = handleScaleRTNCube;
|
selectedHandle = handleScaleRTNCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.LTF) {
|
} else if (directionEnum === SCALE_DIRECTION.LTF) {
|
||||||
directionVector = { x:1, y:-1, z:-1 };
|
directionVector = { x: 1, y: -1, z: -1 };
|
||||||
selectedHandle = handleScaleLTFCube;
|
selectedHandle = handleScaleLTFCube;
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RTF) {
|
} else if (directionEnum === SCALE_DIRECTION.RTF) {
|
||||||
directionVector = { x:-1, y:-1, z:-1 };
|
directionVector = { x: -1, y: -1, z: -1 };
|
||||||
selectedHandle = handleScaleRTFCube;
|
selectedHandle = handleScaleRTFCube;
|
||||||
}
|
}
|
||||||
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
||||||
|
@ -2221,7 +2236,6 @@ SelectionDisplay = (function() {
|
||||||
|
|
||||||
// FUNCTION: UPDATE ROTATION DEGREES OVERLAY
|
// FUNCTION: UPDATE ROTATION DEGREES OVERLAY
|
||||||
function updateRotationDegreesOverlay(angleFromZero, position) {
|
function updateRotationDegreesOverlay(angleFromZero, position) {
|
||||||
var angle = angleFromZero * (Math.PI / 180);
|
|
||||||
var toCameraDistance = getDistanceToCamera(position);
|
var toCameraDistance = getDistanceToCamera(position);
|
||||||
var overlayProps = {
|
var overlayProps = {
|
||||||
position: position,
|
position: position,
|
||||||
|
@ -2412,9 +2426,10 @@ SelectionDisplay = (function() {
|
||||||
|
|
||||||
var startAtCurrent = 0;
|
var startAtCurrent = 0;
|
||||||
var endAtCurrent = angleFromZero;
|
var endAtCurrent = angleFromZero;
|
||||||
|
var maxDegrees = 360;
|
||||||
if (angleFromZero < 0) {
|
if (angleFromZero < 0) {
|
||||||
startAtCurrent = 360 + angleFromZero;
|
startAtCurrent = maxDegrees + angleFromZero;
|
||||||
endAtCurrent = 360;
|
endAtCurrent = maxDegrees;
|
||||||
}
|
}
|
||||||
Overlays.editOverlay(handleRotateCurrentRing, {
|
Overlays.editOverlay(handleRotateCurrentRing, {
|
||||||
startAt: startAtCurrent,
|
startAt: startAtCurrent,
|
||||||
|
@ -2426,8 +2441,9 @@ SelectionDisplay = (function() {
|
||||||
if (spaceMode === SPACE_LOCAL) {
|
if (spaceMode === SPACE_LOCAL) {
|
||||||
Overlays.editOverlay(handleRotateCurrentRing, { rotation: worldRotationZ });
|
Overlays.editOverlay(handleRotateCurrentRing, { rotation: worldRotationZ });
|
||||||
} else {
|
} else {
|
||||||
|
var rotationDegrees = 90;
|
||||||
Overlays.editOverlay(handleRotateCurrentRing, {
|
Overlays.editOverlay(handleRotateCurrentRing, {
|
||||||
rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0)
|
rotation: Quat.fromPitchYawRollDegrees(-rotationDegrees, 0, 0)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,8 @@
|
||||||
// Computes SSIM - see https://en.wikipedia.org/wiki/Structural_similarity
|
// Computes SSIM - see https://en.wikipedia.org/wiki/Structural_similarity
|
||||||
// The value is computed for the luminance component and the average value is returned
|
// The value is computed for the luminance component and the average value is returned
|
||||||
double ImageComparer::compareImages(QImage resultImage, QImage expectedImage) const {
|
double ImageComparer::compareImages(QImage resultImage, QImage expectedImage) const {
|
||||||
// Make sure the image is 8 bits per colour
|
|
||||||
QImage::Format format = expectedImage.format();
|
|
||||||
if (format != QImage::Format::Format_ARGB32) {
|
|
||||||
throw -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int L = 255; // (2^number of bits per pixel) - 1
|
const int L = 255; // (2^number of bits per pixel) - 1
|
||||||
|
|
||||||
const double K1 { 0.01 };
|
const double K1 { 0.01 };
|
||||||
const double K2 { 0.03 };
|
const double K2 { 0.03 };
|
||||||
const double c1 = pow((K1 * L), 2);
|
const double c1 = pow((K1 * L), 2);
|
||||||
|
|
|
@ -25,6 +25,11 @@ extern AutoTester* autoTester;
|
||||||
|
|
||||||
Test::Test() {
|
Test::Test() {
|
||||||
mismatchWindow.setModal(true);
|
mismatchWindow.setModal(true);
|
||||||
|
|
||||||
|
if (autoTester) {
|
||||||
|
autoTester->setUserText("highfidelity");
|
||||||
|
autoTester->setBranchText("master");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Test::createTestResultsFolderPath(const QString& directory) {
|
bool Test::createTestResultsFolderPath(const QString& directory) {
|
||||||
|
@ -63,7 +68,6 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar)
|
||||||
|
|
||||||
// Loop over both lists and compare each pair of images
|
// Loop over both lists and compare each pair of images
|
||||||
// Quit loop if user has aborted due to a failed test.
|
// Quit loop if user has aborted due to a failed test.
|
||||||
const double THRESHOLD { 0.9995 };
|
|
||||||
bool success{ true };
|
bool success{ true };
|
||||||
bool keepOn{ true };
|
bool keepOn{ true };
|
||||||
for (int i = 0; keepOn && i < expectedImagesFullFilenames.length(); ++i) {
|
for (int i = 0; keepOn && i < expectedImagesFullFilenames.length(); ++i) {
|
||||||
|
@ -71,17 +75,14 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar)
|
||||||
QImage resultImage(resultImagesFullFilenames[i]);
|
QImage resultImage(resultImagesFullFilenames[i]);
|
||||||
QImage expectedImage(expectedImagesFullFilenames[i]);
|
QImage expectedImage(expectedImagesFullFilenames[i]);
|
||||||
|
|
||||||
|
double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical
|
||||||
|
|
||||||
|
// similarityIndex is set to -100.0 to indicate images are not the same size
|
||||||
if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) {
|
if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) {
|
||||||
QMessageBox::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);
|
similarityIndex = -100.0;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical
|
|
||||||
try {
|
|
||||||
similarityIndex = imageComparer.compareImages(resultImage, expectedImage);
|
similarityIndex = imageComparer.compareImages(resultImage, expectedImage);
|
||||||
} catch (...) {
|
|
||||||
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Image not in expected format");
|
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (similarityIndex < THRESHOLD) {
|
if (similarityIndex < THRESHOLD) {
|
||||||
|
@ -176,20 +177,25 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai
|
||||||
comparisonImage.save(failureFolderPath + "/" + "Difference Image.png");
|
comparisonImage.save(failureFolderPath + "/" + "Difference Image.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::startTestsEvaluation(const QString& testFolder) {
|
void Test::startTestsEvaluation(const QString& testFolder, const QString& branchFromCommandLine, const QString& userFromCommandLine) {
|
||||||
// Get list of JPEG images in folder, sorted by name
|
if (testFolder.isNull()) {
|
||||||
QString previousSelection = snapshotDirectory;
|
// Get list of JPEG images in folder, sorted by name
|
||||||
QString parent = previousSelection.left(previousSelection.lastIndexOf('/'));
|
QString previousSelection = snapshotDirectory;
|
||||||
if (!parent.isNull() && parent.right(1) != "/") {
|
QString parent = previousSelection.left(previousSelection.lastIndexOf('/'));
|
||||||
parent += "/";
|
if (!parent.isNull() && parent.right(1) != "/") {
|
||||||
}
|
parent += "/";
|
||||||
snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent,
|
}
|
||||||
QFileDialog::ShowDirsOnly);
|
snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent,
|
||||||
|
QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
// If user cancelled then restore previous selection and return
|
// If user cancelled then restore previous selection and return
|
||||||
if (snapshotDirectory == "") {
|
if (snapshotDirectory == "") {
|
||||||
snapshotDirectory = previousSelection;
|
snapshotDirectory = previousSelection;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snapshotDirectory = testFolder;
|
||||||
|
exitWhenComplete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit if test results folder could not be created
|
// Quit if test results folder could not be created
|
||||||
|
@ -197,17 +203,6 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before any processing - all images are converted to PNGs, as this is the format stored on GitHub
|
|
||||||
QStringList sortedSnapshotFilenames = createListOfAll_imagesInDirectory("jpg", snapshotDirectory);
|
|
||||||
foreach(QString filename, sortedSnapshotFilenames) {
|
|
||||||
QString filenameWithoutExtension = filename.left(filename.length() - 4);
|
|
||||||
copyJPGtoPNG(snapshotDirectory + "/" + filenameWithoutExtension + ".jpg",
|
|
||||||
snapshotDirectory + "/" + filenameWithoutExtension + ".png"
|
|
||||||
);
|
|
||||||
|
|
||||||
QFile::remove(snapshotDirectory + "/" + filenameWithoutExtension + ".jpg");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create two lists. The first is the test results, the second is the expected images
|
// Create two lists. The first is the test results, the second is the expected images
|
||||||
// The expected images are represented as a URL to enable download from GitHub
|
// The expected images are represented as a URL to enable download from GitHub
|
||||||
// Images that are in the wrong format are ignored.
|
// Images that are in the wrong format are ignored.
|
||||||
|
@ -219,6 +214,9 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
||||||
expectedImagesFilenames.clear();
|
expectedImagesFilenames.clear();
|
||||||
expectedImagesFullFilenames.clear();
|
expectedImagesFullFilenames.clear();
|
||||||
|
|
||||||
|
QString branch = (branchFromCommandLine.isNull()) ? autoTester->getSelectedBranch() : branchFromCommandLine;
|
||||||
|
QString user = (userFromCommandLine.isNull()) ? autoTester->getSelectedUser() : userFromCommandLine;
|
||||||
|
|
||||||
foreach(QString currentFilename, sortedTestResultsFilenames) {
|
foreach(QString currentFilename, sortedTestResultsFilenames) {
|
||||||
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
||||||
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
||||||
|
@ -231,7 +229,7 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
||||||
QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS);
|
QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS);
|
||||||
QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png";
|
QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png";
|
||||||
|
|
||||||
QString imageURLString("https://raw.githubusercontent.com/" + GIT_HUB_USER + "/hifi_tests/" + GIT_HUB_BRANCH + "/" +
|
QString imageURLString("https://raw.githubusercontent.com/" + user + "/" + GIT_HUB_REPOSITORY + "/" + branch + "/" +
|
||||||
expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename);
|
expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename);
|
||||||
|
|
||||||
expectedImagesURLs << imageURLString;
|
expectedImagesURLs << imageURLString;
|
||||||
|
@ -259,6 +257,10 @@ void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactive
|
||||||
}
|
}
|
||||||
|
|
||||||
zipAndDeleteTestResultsFolder();
|
zipAndDeleteTestResultsFolder();
|
||||||
|
|
||||||
|
if (exitWhenComplete) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Test::isAValidDirectory(const QString& pathname) {
|
bool Test::isAValidDirectory(const QString& pathname) {
|
||||||
|
@ -299,10 +301,9 @@ QString Test::extractPathFromTestsDown(const QString& fullPath) {
|
||||||
|
|
||||||
void Test::includeTest(QTextStream& textStream, const QString& testPathname) {
|
void Test::includeTest(QTextStream& textStream, const QString& testPathname) {
|
||||||
QString partialPath = extractPathFromTestsDown(testPathname);
|
QString partialPath = extractPathFromTestsDown(testPathname);
|
||||||
textStream << "Script.include(\""
|
QString partialPathWithoutTests = partialPath.right(partialPath.length() - 7);
|
||||||
<< "https://github.com/" << GIT_HUB_USER << "/hifi_tests/blob/" << GIT_HUB_BRANCH
|
|
||||||
<< partialPath + "?raw=true\");"
|
textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << endl;
|
||||||
<< endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a single script in a user-selected folder.
|
// Creates a single script in a user-selected folder.
|
||||||
|
@ -397,12 +398,20 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact
|
||||||
const QString DATE_TIME_FORMAT("MMM d yyyy, h:mm");
|
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 << "// This is an automatically generated file, created by auto-tester on " << QDateTime::currentDateTime().toString(DATE_TIME_FORMAT) << endl << endl;
|
||||||
|
|
||||||
textStream << "user = \"" + GIT_HUB_USER + "/\";" << endl;
|
// Include 'autoTest.js'
|
||||||
textStream << "repository = \"" + GIT_HUB_REPOSITORY + "/\";" << endl;
|
QString branch = autoTester->getSelectedBranch();
|
||||||
textStream << "branch = \"" + GIT_HUB_BRANCH + "/\";" << endl << endl;
|
QString user = autoTester->getSelectedUser();
|
||||||
|
|
||||||
textStream << "var autoTester = Script.require(\"https://github.com/" + GIT_HUB_USER + "/hifi_tests/blob/"
|
textStream << "PATH_TO_THE_REPO_PATH_UTILS_FILE = \"https://raw.githubusercontent.com/" + user + "/hifi_tests/" + branch + "/tests/utils/branchUtils.js\";" << endl;
|
||||||
+ GIT_HUB_BRANCH + "/tests/utils/autoTester.js?raw=true\");" << endl << endl;
|
textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl;
|
||||||
|
textStream << "var autoTester = createAutoTester(Script.resolvePath(\".\"));" << endl << endl;
|
||||||
|
|
||||||
|
textStream << "var testsRootPath = autoTester.getTestsRootPath();" << endl << endl;
|
||||||
|
|
||||||
|
// Wait 10 seconds before starting
|
||||||
|
textStream << "if (typeof Test !== 'undefined') {" << endl;
|
||||||
|
textStream << " Test.wait(10000);" << endl;
|
||||||
|
textStream << "};" << endl << endl;
|
||||||
|
|
||||||
textStream << "autoTester.enableRecursive();" << endl;
|
textStream << "autoTester.enableRecursive();" << endl;
|
||||||
textStream << "autoTester.enableAuto();" << endl << endl;
|
textStream << "autoTester.enableAuto();" << endl << endl;
|
||||||
|
@ -498,13 +507,13 @@ void Test::createTests() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("jpg", snapshotDirectory);
|
QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("png", snapshotDirectory);
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
const int maxImages = pow(10, NUM_DIGITS);
|
const int maxImages = pow(10, NUM_DIGITS);
|
||||||
foreach (QString currentFilename, sortedImageFilenames) {
|
foreach (QString currentFilename, sortedImageFilenames) {
|
||||||
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
||||||
if (isInSnapshotFilenameFormat("jpg", currentFilename)) {
|
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
||||||
if (i >= maxImages) {
|
if (i >= maxImages) {
|
||||||
QMessageBox::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);
|
exit(-1);
|
||||||
|
@ -528,9 +537,12 @@ void Test::createTests() {
|
||||||
fullNewFileName += "/" + newFilename;
|
fullNewFileName += "/" + newFilename;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
copyJPGtoPNG(fullCurrentFilename, fullNewFileName);
|
if (QFile::exists(fullNewFileName)) {
|
||||||
|
QFile::remove(fullNewFileName);
|
||||||
|
}
|
||||||
|
QFile::copy(fullCurrentFilename, fullNewFileName);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
QMessageBox::critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nTest creation aborted");
|
QMessageBox::critical(0, "Error", "Could not copy file: " + fullCurrentFilename + " to " + fullNewFileName + "\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
|
@ -560,9 +572,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) {
|
||||||
const QString ws("\\h*"); //white-space character
|
const QString ws("\\h*"); //white-space character
|
||||||
const QString functionPerformName(ws + "autoTester" + ws + "\\." + ws + "perform");
|
const QString functionPerformName(ws + "autoTester" + ws + "\\." + ws + "perform");
|
||||||
const QString quotedString("\\\".+\\\"");
|
const QString quotedString("\\\".+\\\"");
|
||||||
const QString ownPath("Script" + ws + "\\." + ws + "resolvePath" + ws + "\\(" + ws + "\\\"\\.\\\"" + ws + "\\)");
|
QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString);
|
||||||
const QString functionParameter("function" + ws + "\\(testType" + ws + "\\)");
|
|
||||||
QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString + "\\," + ws + ownPath + "\\," + ws + functionParameter + ws + "{" + ".*");
|
|
||||||
QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle);
|
QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle);
|
||||||
|
|
||||||
|
|
||||||
|
@ -811,19 +821,6 @@ void Test::createTestsOutline() {
|
||||||
QMessageBox::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) {
|
|
||||||
QFile::remove(destinationPNGFullFilename);
|
|
||||||
|
|
||||||
QImageReader reader;
|
|
||||||
reader.setFileName(sourceJPGFullFilename);
|
|
||||||
|
|
||||||
QImage image = reader.read();
|
|
||||||
|
|
||||||
QImageWriter writer;
|
|
||||||
writer.setFileName(destinationPNGFullFilename);
|
|
||||||
writer.write(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) {
|
QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) {
|
||||||
imageDirectory = QDir(pathToImageDirectory);
|
imageDirectory = QDir(pathToImageDirectory);
|
||||||
QStringList nameFilters;
|
QStringList nameFilters;
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Test {
|
||||||
public:
|
public:
|
||||||
Test();
|
Test();
|
||||||
|
|
||||||
void startTestsEvaluation(const QString& testFolder = QString());
|
void startTestsEvaluation(const QString& testFolder = QString(), const QString& branchFromCommandLine = QString(), const QString& userFromCommandLine = QString());
|
||||||
void finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar);
|
void finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar);
|
||||||
|
|
||||||
void createRecursiveScript();
|
void createRecursiveScript();
|
||||||
|
@ -69,13 +69,13 @@ public:
|
||||||
QString getExpectedImageDestinationDirectory(const QString& filename);
|
QString getExpectedImageDestinationDirectory(const QString& filename);
|
||||||
QString getExpectedImagePartialSourceDirectory(const QString& filename);
|
QString getExpectedImagePartialSourceDirectory(const QString& filename);
|
||||||
|
|
||||||
void copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString TEST_FILENAME { "test.js" };
|
const QString TEST_FILENAME { "test.js" };
|
||||||
const QString TEST_RESULTS_FOLDER { "TestResults" };
|
const QString TEST_RESULTS_FOLDER { "TestResults" };
|
||||||
const QString TEST_RESULTS_FILENAME { "TestResults.txt" };
|
const QString TEST_RESULTS_FILENAME { "TestResults.txt" };
|
||||||
|
|
||||||
|
const double THRESHOLD{ 0.96 };
|
||||||
|
|
||||||
QDir imageDirectory;
|
QDir imageDirectory;
|
||||||
|
|
||||||
MismatchWindow mismatchWindow;
|
MismatchWindow mismatchWindow;
|
||||||
|
@ -102,9 +102,7 @@ private:
|
||||||
QStringList resultImagesFullFilenames;
|
QStringList resultImagesFullFilenames;
|
||||||
|
|
||||||
// Used for accessing GitHub
|
// Used for accessing GitHub
|
||||||
const QString GIT_HUB_USER{ "highfidelity" };
|
|
||||||
const QString GIT_HUB_REPOSITORY{ "hifi_tests" };
|
const QString GIT_HUB_REPOSITORY{ "hifi_tests" };
|
||||||
const QString GIT_HUB_BRANCH{ "master" };
|
|
||||||
|
|
||||||
const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" };
|
const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" };
|
||||||
|
|
||||||
|
@ -115,6 +113,8 @@ private:
|
||||||
// var pathSeparator = ".";
|
// var pathSeparator = ".";
|
||||||
const QString ADVANCE_KEY{ "n" };
|
const QString ADVANCE_KEY{ "n" };
|
||||||
const QString PATH_SEPARATOR{ "." };
|
const QString PATH_SEPARATOR{ "." };
|
||||||
|
|
||||||
|
bool exitWhenComplete{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_test_h
|
#endif // hifi_test_h
|
|
@ -10,23 +10,63 @@
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include "ui/AutoTester.h"
|
#include "ui/AutoTester.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
AutoTester* autoTester;
|
AutoTester* autoTester;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// Only parameter is "--testFolder"
|
// If no parameters then run in interactive mode
|
||||||
|
// Parameter --testFolder <folder containing the test images>
|
||||||
|
// Parameter --branch <branch on GitHub>
|
||||||
|
// default is "master"
|
||||||
|
// Parameter --user <GitHub user>
|
||||||
|
// default is "highfidelity"
|
||||||
|
// Parameter --repository <repository on GitHub>
|
||||||
|
// default is "highfidelity"
|
||||||
|
|
||||||
QString testFolder;
|
QString testFolder;
|
||||||
if (argc == 3) {
|
|
||||||
if (QString(argv[1]) == "--testFolder") {
|
QString branch{ "master" };
|
||||||
testFolder = QString(argv[2]);
|
QString user{ "highfidelity" };
|
||||||
|
|
||||||
|
for (int i = 1; i < argc - 1; ++i) {
|
||||||
|
if (QString(argv[i]) == "--testFolder") {
|
||||||
|
++i;
|
||||||
|
if (i < argc) {
|
||||||
|
testFolder = QString(argv[i]);
|
||||||
|
} else {
|
||||||
|
std::cout << "Missing parameter after --testFolder" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else if (QString(argv[i]) == "--branch") {
|
||||||
|
++i;
|
||||||
|
if (i < argc) {
|
||||||
|
branch = QString(argv[i]);
|
||||||
|
} else {
|
||||||
|
std::cout << "Missing parameter after --branch" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else if (QString(argv[i]) == "--user") {
|
||||||
|
++i;
|
||||||
|
if (i < argc) {
|
||||||
|
user = QString(argv[i]);
|
||||||
|
} else {
|
||||||
|
std::cout << "Missing parameter after --user" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Unknown parameter" << std::endl;
|
||||||
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QApplication application(argc, argv);
|
QApplication application(argc, argv);
|
||||||
|
|
||||||
autoTester = new AutoTester();
|
autoTester = new AutoTester();
|
||||||
|
autoTester->setup();
|
||||||
|
|
||||||
if (!testFolder.isNull()) {
|
if (!testFolder.isNull()) {
|
||||||
autoTester->runFromCommandLine(testFolder);
|
autoTester->runFromCommandLine(testFolder, branch, user);
|
||||||
} else {
|
} else {
|
||||||
autoTester->show();
|
autoTester->show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,15 @@ AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) {
|
||||||
ui.hideTaskbarButton->setVisible(false);
|
ui.hideTaskbarButton->setVisible(false);
|
||||||
ui.showTaskbarButton->setVisible(false);
|
ui.showTaskbarButton->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoTester::setup() {
|
||||||
test = new Test();
|
test = new Test();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTester::runFromCommandLine(const QString& testFolder) {
|
void AutoTester::runFromCommandLine(const QString& testFolder, const QString& branch, const QString& user) {
|
||||||
isRunningFromCommandline = true;
|
isRunningFromCommandline = true;
|
||||||
test->startTestsEvaluation(testFolder);
|
test->startTestsEvaluation(testFolder, branch, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTester::on_evaluateTestsButton_clicked() {
|
void AutoTester::on_evaluateTestsButton_clicked() {
|
||||||
|
@ -116,6 +118,7 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director
|
||||||
ui.progressBar->setValue(0);
|
ui.progressBar->setValue(0);
|
||||||
ui.progressBar->setVisible(true);
|
ui.progressBar->setVisible(true);
|
||||||
|
|
||||||
|
downloaders.clear();
|
||||||
for (int i = 0; i < _numberOfImagesToDownload; ++i) {
|
for (int i = 0; i < _numberOfImagesToDownload; ++i) {
|
||||||
QUrl imageURL(URLs[i]);
|
QUrl imageURL(URLs[i]);
|
||||||
downloadImage(imageURL);
|
downloadImage(imageURL);
|
||||||
|
@ -125,14 +128,12 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTester::saveImage(int index) {
|
void AutoTester::saveImage(int index) {
|
||||||
QPixmap pixmap;
|
try {
|
||||||
pixmap.loadFromData(downloaders[index]->downloadedData());
|
QFile file(_directoryName + "/" + _filenames[index]);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
QImage image = pixmap.toImage();
|
file.write(downloaders[index]->downloadedData());
|
||||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
file.close();
|
||||||
|
} catch (...) {
|
||||||
QString fullPathname = _directoryName + "/" + _filenames[index];
|
|
||||||
if (!image.save(fullPathname, 0, 100)) {
|
|
||||||
QMessageBox::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);
|
ui.progressBar->setVisible(false);
|
||||||
return;
|
return;
|
||||||
|
@ -141,6 +142,7 @@ void AutoTester::saveImage(int index) {
|
||||||
++_numberOfImagesDownloaded;
|
++_numberOfImagesDownloaded;
|
||||||
|
|
||||||
if (_numberOfImagesDownloaded == _numberOfImagesToDownload) {
|
if (_numberOfImagesDownloaded == _numberOfImagesToDownload) {
|
||||||
|
disconnect(signalMapper, SIGNAL (mapped(int)), this, SLOT (saveImage(int)));
|
||||||
test->finishTestsEvaluation(isRunningFromCommandline, ui.checkBoxInteractiveMode->isChecked(), ui.progressBar);
|
test->finishTestsEvaluation(isRunningFromCommandline, ui.checkBoxInteractiveMode->isChecked(), ui.progressBar);
|
||||||
} else {
|
} else {
|
||||||
ui.progressBar->setValue(_numberOfImagesDownloaded);
|
ui.progressBar->setValue(_numberOfImagesDownloaded);
|
||||||
|
@ -150,3 +152,20 @@ void AutoTester::saveImage(int index) {
|
||||||
void AutoTester::about() {
|
void AutoTester::about() {
|
||||||
QMessageBox::information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__);
|
QMessageBox::information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoTester::setUserText(const QString& user) {
|
||||||
|
ui.userTextEdit->setText(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AutoTester::getSelectedUser()
|
||||||
|
{
|
||||||
|
return ui.userTextEdit->toPlainText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoTester::setBranchText(const QString& branch) {
|
||||||
|
ui.branchTextEdit->setText(branch);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AutoTester::getSelectedBranch() {
|
||||||
|
return ui.branchTextEdit->toPlainText();
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <QtWidgets/QMainWindow>
|
#include <QtWidgets/QMainWindow>
|
||||||
#include <QSignalMapper>
|
#include <QSignalMapper>
|
||||||
|
#include <QTextEdit>
|
||||||
#include "ui_AutoTester.h"
|
#include "ui_AutoTester.h"
|
||||||
|
|
||||||
#include "../Downloader.h"
|
#include "../Downloader.h"
|
||||||
|
@ -23,11 +24,19 @@ class AutoTester : public QMainWindow {
|
||||||
public:
|
public:
|
||||||
AutoTester(QWidget *parent = Q_NULLPTR);
|
AutoTester(QWidget *parent = Q_NULLPTR);
|
||||||
|
|
||||||
void runFromCommandLine(const QString& testFolder);
|
void setup();
|
||||||
|
|
||||||
|
void runFromCommandLine(const QString& testFolder, const QString& branch, const QString& user);
|
||||||
|
|
||||||
void downloadImage(const QUrl& url);
|
void downloadImage(const QUrl& url);
|
||||||
void downloadImages(const QStringList& URLs, const QString& directoryName, const QStringList& filenames);
|
void downloadImages(const QStringList& URLs, const QString& directoryName, const QStringList& filenames);
|
||||||
|
|
||||||
|
void setUserText(const QString& user);
|
||||||
|
QString getSelectedUser();
|
||||||
|
|
||||||
|
void setBranchText(const QString& branch);
|
||||||
|
QString getSelectedBranch();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_evaluateTestsButton_clicked();
|
void on_evaluateTestsButton_clicked();
|
||||||
void on_createRecursiveScriptButton_clicked();
|
void on_createRecursiveScriptButton_clicked();
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>607</width>
|
<width>612</width>
|
||||||
<height>514</height>
|
<height>537</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -17,9 +17,9 @@
|
||||||
<widget class="QPushButton" name="closeButton">
|
<widget class="QPushButton" name="closeButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>360</x>
|
<x>380</x>
|
||||||
<y>400</y>
|
<y>430</y>
|
||||||
<width>220</width>
|
<width>101</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -43,9 +43,9 @@
|
||||||
<widget class="QPushButton" name="evaluateTestsButton">
|
<widget class="QPushButton" name="evaluateTestsButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>20</x>
|
<x>430</x>
|
||||||
<y>285</y>
|
<y>270</y>
|
||||||
<width>220</width>
|
<width>101</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -56,8 +56,8 @@
|
||||||
<widget class="QPushButton" name="createRecursiveScriptButton">
|
<widget class="QPushButton" name="createRecursiveScriptButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>360</x>
|
<x>330</x>
|
||||||
<y>35</y>
|
<y>110</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -69,8 +69,8 @@
|
||||||
<widget class="QCheckBox" name="checkBoxInteractiveMode">
|
<widget class="QCheckBox" name="checkBoxInteractiveMode">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>23</x>
|
<x>320</x>
|
||||||
<y>250</y>
|
<y>280</y>
|
||||||
<width>131</width>
|
<width>131</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -85,8 +85,8 @@
|
||||||
<widget class="QProgressBar" name="progressBar">
|
<widget class="QProgressBar" name="progressBar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>20</x>
|
<x>320</x>
|
||||||
<y>340</y>
|
<y>330</y>
|
||||||
<width>255</width>
|
<width>255</width>
|
||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -98,8 +98,8 @@
|
||||||
<widget class="QPushButton" name="createAllRecursiveScriptsButton">
|
<widget class="QPushButton" name="createAllRecursiveScriptsButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>360</x>
|
<x>330</x>
|
||||||
<y>100</y>
|
<y>170</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>20</x>
|
<x>20</x>
|
||||||
<y>80</y>
|
<y>110</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>20</x>
|
<x>20</x>
|
||||||
<y>130</y>
|
<y>160</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>20</x>
|
<x>20</x>
|
||||||
<y>180</y>
|
<y>250</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -150,27 +150,83 @@
|
||||||
<widget class="QPushButton" name="showTaskbarButton">
|
<widget class="QPushButton" name="showTaskbarButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>490</x>
|
<x>10</x>
|
||||||
<y>280</y>
|
<y>440</y>
|
||||||
<width>91</width>
|
<width>211</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Taskbar</string>
|
<string>Show Windows Taskbar</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="hideTaskbarButton">
|
<widget class="QPushButton" name="hideTaskbarButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>490</x>
|
<x>10</x>
|
||||||
<y>230</y>
|
<y>390</y>
|
||||||
<width>91</width>
|
<width>211</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Hide Taskbar</string>
|
<string>Hide Windows Taskbar</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>330</x>
|
||||||
|
<y>55</y>
|
||||||
|
<width>81</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>GitHub Branch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>330</x>
|
||||||
|
<y>15</y>
|
||||||
|
<width>81</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>GitHub User</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTextEdit" name="userTextEdit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>420</x>
|
||||||
|
<y>12</y>
|
||||||
|
<width>140</width>
|
||||||
|
<height>24</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTextEdit" name="branchTextEdit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>420</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>140</width>
|
||||||
|
<height>24</height>
|
||||||
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -179,7 +235,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>607</width>
|
<width>612</width>
|
||||||
<height>21</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|
Loading…
Reference in a new issue