mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 11:41:17 +02:00
Merge branch 'master' into bug/5950
This commit is contained in:
commit
d5c88bc6de
178 changed files with 5247 additions and 2289 deletions
|
@ -16,6 +16,7 @@
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
#include <AddressManager.h>
|
#include <AddressManager.h>
|
||||||
#include <Assignment.h>
|
#include <Assignment.h>
|
||||||
|
@ -141,7 +142,7 @@ void AssignmentClient::stopAssignmentClient() {
|
||||||
QThread* currentAssignmentThread = _currentAssignment->thread();
|
QThread* currentAssignmentThread = _currentAssignment->thread();
|
||||||
|
|
||||||
// ask the current assignment to stop
|
// ask the current assignment to stop
|
||||||
QMetaObject::invokeMethod(_currentAssignment, "stop", Qt::BlockingQueuedConnection);
|
BLOCKING_INVOKE_METHOD(_currentAssignment, "stop");
|
||||||
|
|
||||||
// ask the current assignment to delete itself on its thread
|
// ask the current assignment to delete itself on its thread
|
||||||
_currentAssignment->deleteLater();
|
_currentAssignment->deleteLater();
|
||||||
|
|
|
@ -9,8 +9,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
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
#include "AssignmentClientApp.h"
|
||||||
#include <QThread>
|
|
||||||
|
#include <QtCore/QCommandLineParser>
|
||||||
|
#include <QtCore/QDir>
|
||||||
|
#include <QtCore/QStandardPaths>
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
@ -20,10 +24,6 @@
|
||||||
#include "Assignment.h"
|
#include "Assignment.h"
|
||||||
#include "AssignmentClient.h"
|
#include "AssignmentClient.h"
|
||||||
#include "AssignmentClientMonitor.h"
|
#include "AssignmentClientMonitor.h"
|
||||||
#include "AssignmentClientApp.h"
|
|
||||||
#include <QtCore/QDir>
|
|
||||||
#include <QtCore/QStandardPaths>
|
|
||||||
|
|
||||||
|
|
||||||
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
||||||
QCoreApplication(argc, argv)
|
QCoreApplication(argc, argv)
|
||||||
|
@ -87,6 +87,9 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
||||||
const QCommandLineOption logDirectoryOption(ASSIGNMENT_LOG_DIRECTORY, "directory to store logs", "log-directory");
|
const QCommandLineOption logDirectoryOption(ASSIGNMENT_LOG_DIRECTORY, "directory to store logs", "log-directory");
|
||||||
parser.addOption(logDirectoryOption);
|
parser.addOption(logDirectoryOption);
|
||||||
|
|
||||||
|
const QCommandLineOption parentPIDOption(PARENT_PID_OPTION, "PID of the parent process", "parent-pid");
|
||||||
|
parser.addOption(parentPIDOption);
|
||||||
|
|
||||||
if (!parser.parse(QCoreApplication::arguments())) {
|
if (!parser.parse(QCoreApplication::arguments())) {
|
||||||
qCritical() << parser.errorText() << endl;
|
qCritical() << parser.errorText() << endl;
|
||||||
parser.showHelp();
|
parser.showHelp();
|
||||||
|
@ -203,6 +206,16 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(parentPIDOption)) {
|
||||||
|
bool ok = false;
|
||||||
|
int parentPID = parser.value(parentPIDOption).toInt(&ok);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
qDebug() << "Parent process PID is" << parentPID;
|
||||||
|
watchParentProcess(parentPID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QThread::currentThread()->setObjectName("main thread");
|
QThread::currentThread()->setObjectName("main thread");
|
||||||
|
|
||||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||||
|
|
|
@ -131,7 +131,6 @@ void AssignmentClientMonitor::aboutToQuit() {
|
||||||
void AssignmentClientMonitor::spawnChildClient() {
|
void AssignmentClientMonitor::spawnChildClient() {
|
||||||
QProcess* assignmentClient = new QProcess(this);
|
QProcess* assignmentClient = new QProcess(this);
|
||||||
|
|
||||||
|
|
||||||
// unparse the parts of the command-line that the child cares about
|
// unparse the parts of the command-line that the child cares about
|
||||||
QStringList _childArguments;
|
QStringList _childArguments;
|
||||||
if (_assignmentPool != "") {
|
if (_assignmentPool != "") {
|
||||||
|
@ -160,6 +159,9 @@ void AssignmentClientMonitor::spawnChildClient() {
|
||||||
_childArguments.append("--" + ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION);
|
_childArguments.append("--" + ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION);
|
||||||
_childArguments.append(QString::number(DependencyManager::get<NodeList>()->getLocalSockAddr().getPort()));
|
_childArguments.append(QString::number(DependencyManager::get<NodeList>()->getLocalSockAddr().getPort()));
|
||||||
|
|
||||||
|
_childArguments.append("--" + PARENT_PID_OPTION);
|
||||||
|
_childArguments.append(QString::number(QCoreApplication::applicationPid()));
|
||||||
|
|
||||||
QString nowString, stdoutFilenameTemp, stderrFilenameTemp, stdoutPathTemp, stderrPathTemp;
|
QString nowString, stdoutFilenameTemp, stderrFilenameTemp, stdoutPathTemp, stderrPathTemp;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,13 @@ void AvatarMixer::start() {
|
||||||
// is guaranteed to not be accessed by other thread
|
// is guaranteed to not be accessed by other thread
|
||||||
void AvatarMixer::manageIdentityData(const SharedNodePointer& node) {
|
void AvatarMixer::manageIdentityData(const SharedNodePointer& node) {
|
||||||
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
|
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
|
||||||
|
|
||||||
|
// there is no need to manage identity data we haven't received yet
|
||||||
|
// so bail early if we've never received an identity packet for this avatar
|
||||||
|
if (!nodeData || !nodeData->getAvatar().hasProcessedFirstIdentity()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool sendIdentity = false;
|
bool sendIdentity = false;
|
||||||
if (nodeData && nodeData->getAvatarSessionDisplayNameMustChange()) {
|
if (nodeData && nodeData->getAvatarSessionDisplayNameMustChange()) {
|
||||||
AvatarData& avatar = nodeData->getAvatar();
|
AvatarData& avatar = nodeData->getAvatar();
|
||||||
|
|
|
@ -320,14 +320,18 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
++numOtherAvatars;
|
++numOtherAvatars;
|
||||||
|
|
||||||
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
|
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
|
||||||
|
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
|
||||||
|
|
||||||
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
|
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
|
||||||
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
|
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
|
||||||
if (nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) {
|
if (otherAvatar->hasProcessedFirstIdentity()
|
||||||
|
&& nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) {
|
||||||
identityBytesSent += sendIdentityPacket(otherNodeData, node);
|
identityBytesSent += sendIdentityPacket(otherNodeData, node);
|
||||||
|
|
||||||
|
// remember the last time we sent identity details about this other node to the receiver
|
||||||
|
nodeData->setLastBroadcastTime(otherNode->getUUID(), usecTimestampNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
|
|
||||||
glm::vec3 otherPosition = otherAvatar->getClientGlobalPosition();
|
glm::vec3 otherPosition = otherAvatar->getClientGlobalPosition();
|
||||||
|
|
||||||
// determine if avatar is in view, to determine how much data to include...
|
// determine if avatar is in view, to determine how much data to include...
|
||||||
|
@ -400,9 +404,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// set the last sent sequence number for this sender on the receiver
|
// set the last sent sequence number for this sender on the receiver
|
||||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
||||||
otherNodeData->getLastReceivedSequenceNumber());
|
otherNodeData->getLastReceivedSequenceNumber());
|
||||||
|
|
||||||
// remember the last time we sent details about this other node to the receiver
|
|
||||||
nodeData->setLastBroadcastTime(otherNode->getUUID(), start);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <AnimUtil.h>
|
#include <AnimUtil.h>
|
||||||
#include "ScriptableAvatar.h"
|
#include "ScriptableAvatar.h"
|
||||||
|
@ -49,7 +50,7 @@ void ScriptableAvatar::stopAnimation() {
|
||||||
AnimationDetails ScriptableAvatar::getAnimationDetails() {
|
AnimationDetails ScriptableAvatar::getAnimationDetails() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
AnimationDetails result;
|
AnimationDetails result;
|
||||||
QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "getAnimationDetails",
|
||||||
Q_RETURN_ARG(AnimationDetails, result));
|
Q_RETURN_ARG(AnimationDetails, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
12
cmake/macros/TargetLeapMotion.cmake
Normal file
12
cmake/macros/TargetLeapMotion.cmake
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#
|
||||||
|
# Created by David Rowe on 16 Jun 2017.
|
||||||
|
# Copyright 2017 High Fidelity, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the Apache License, Version 2.0.
|
||||||
|
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
#
|
||||||
|
|
||||||
|
macro(TARGET_LEAPMOTION)
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE ${LEAPMOTION_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${TARGET_NAME} ${LEAPMOTION_LIBRARIES})
|
||||||
|
endmacro()
|
|
@ -56,19 +56,17 @@ elseif (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
function(_fbx_find_library _name _lib _suffix)
|
function(_fbx_find_library _name _lib _suffix)
|
||||||
if (MSVC12)
|
if (MSVC_VERSION EQUAL 1910)
|
||||||
|
set(VS_PREFIX vs2017)
|
||||||
|
elseif (MSVC_VERSION EQUAL 1900)
|
||||||
|
set(VS_PREFIX vs2015)
|
||||||
|
elseif (MSVC_VERSION EQUAL 1800)
|
||||||
set(VS_PREFIX vs2013)
|
set(VS_PREFIX vs2013)
|
||||||
endif()
|
elseif (MSVC_VERSION EQUAL 1700)
|
||||||
|
|
||||||
if (MSVC11)
|
|
||||||
set(VS_PREFIX vs2012)
|
set(VS_PREFIX vs2012)
|
||||||
endif()
|
elseif (MSVC_VERSION EQUAL 1600)
|
||||||
|
|
||||||
if (MSVC10)
|
|
||||||
set(VS_PREFIX vs2010)
|
set(VS_PREFIX vs2010)
|
||||||
endif()
|
elseif (MSVC_VERSION EQUAL 1500)
|
||||||
|
|
||||||
if (MSVC90)
|
|
||||||
set(VS_PREFIX vs2008)
|
set(VS_PREFIX vs2008)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
{
|
{
|
||||||
"name": "descriptors",
|
"name": "descriptors",
|
||||||
"label": "Description",
|
"label": "Description",
|
||||||
|
"restart": false,
|
||||||
"help": "This data will be queryable from your server. It may be collected by High Fidelity and used to share your domain with others.",
|
"help": "This data will be queryable from your server. It may be collected by High Fidelity and used to share your domain with others.",
|
||||||
"settings": [
|
"settings": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -162,8 +162,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
|
|
||||||
_gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request
|
_gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request
|
||||||
|
|
||||||
|
//send signal to DomainMetadata when descriptors changed
|
||||||
_metadata = new DomainMetadata(this);
|
_metadata = new DomainMetadata(this);
|
||||||
|
connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated,
|
||||||
|
_metadata, &DomainMetadata::descriptorsChanged);
|
||||||
|
|
||||||
qDebug() << "domain-server is running";
|
qDebug() << "domain-server is running";
|
||||||
static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist";
|
static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist";
|
||||||
|
@ -221,6 +223,8 @@ void DomainServer::parseCommandLine() {
|
||||||
const QCommandLineOption masterConfigOption("master-config", "Deprecated config-file option");
|
const QCommandLineOption masterConfigOption("master-config", "Deprecated config-file option");
|
||||||
parser.addOption(masterConfigOption);
|
parser.addOption(masterConfigOption);
|
||||||
|
|
||||||
|
const QCommandLineOption parentPIDOption(PARENT_PID_OPTION, "PID of the parent process", "parent-pid");
|
||||||
|
parser.addOption(parentPIDOption);
|
||||||
|
|
||||||
if (!parser.parse(QCoreApplication::arguments())) {
|
if (!parser.parse(QCoreApplication::arguments())) {
|
||||||
qWarning() << parser.errorText() << endl;
|
qWarning() << parser.errorText() << endl;
|
||||||
|
@ -249,6 +253,17 @@ void DomainServer::parseCommandLine() {
|
||||||
_overrideDomainID = true;
|
_overrideDomainID = true;
|
||||||
qDebug() << "domain-server ID is" << _overridingDomainID;
|
qDebug() << "domain-server ID is" << _overridingDomainID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (parser.isSet(parentPIDOption)) {
|
||||||
|
bool ok = false;
|
||||||
|
int parentPID = parser.value(parentPIDOption).toInt(&ok);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
qDebug() << "Parent process PID is" << parentPID;
|
||||||
|
watchParentProcess(parentPID);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DomainServer::~DomainServer() {
|
DomainServer::~DomainServer() {
|
||||||
|
|
|
@ -1198,7 +1198,8 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
|
||||||
static const QString SECURITY_ROOT_KEY = "security";
|
static const QString SECURITY_ROOT_KEY = "security";
|
||||||
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
|
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
|
||||||
static const QString BROADCASTING_KEY = "broadcasting";
|
static const QString BROADCASTING_KEY = "broadcasting";
|
||||||
|
static const QString DESCRIPTION_ROOT_KEY = "descriptors";
|
||||||
|
|
||||||
auto& settingsVariant = _configMap.getConfig();
|
auto& settingsVariant = _configMap.getConfig();
|
||||||
bool needRestart = false;
|
bool needRestart = false;
|
||||||
|
|
||||||
|
@ -1265,7 +1266,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
|
||||||
if (!matchingDescriptionObject.isEmpty()) {
|
if (!matchingDescriptionObject.isEmpty()) {
|
||||||
const QJsonValue& settingValue = rootValue.toObject()[settingKey];
|
const QJsonValue& settingValue = rootValue.toObject()[settingKey];
|
||||||
updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject);
|
updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject);
|
||||||
if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY)
|
if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != DESCRIPTION_ROOT_KEY)
|
||||||
|| settingKey == AC_SUBNET_WHITELIST_KEY) {
|
|| settingKey == AC_SUBNET_WHITELIST_KEY) {
|
||||||
needRestart = true;
|
needRestart = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,7 @@ void RenderingClient::sendAvatarPacket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingClient::cleanupBeforeQuit() {
|
void RenderingClient::cleanupBeforeQuit() {
|
||||||
|
DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
|
||||||
"stop", Qt::BlockingQueuedConnection);
|
|
||||||
|
|
||||||
// destroy the AudioClient so it and its thread will safely go down
|
// destroy the AudioClient so it and its thread will safely go down
|
||||||
DependencyManager::destroy<AudioClient>();
|
DependencyManager::destroy<AudioClient>();
|
||||||
}
|
}
|
||||||
|
|
8
interface/external/leapmotion/readme.txt
vendored
8
interface/external/leapmotion/readme.txt
vendored
|
@ -10,7 +10,7 @@ Interface has been tested with SDK versions:
|
||||||
1. Copy the LeapSDK folders from the LeapDeveloperKit installation directory (Lib, Include) into the interface/externals/leapmotion folder.
|
1. Copy the LeapSDK folders from the LeapDeveloperKit installation directory (Lib, Include) into the interface/externals/leapmotion folder.
|
||||||
This readme.txt should be there as well.
|
This readme.txt should be there as well.
|
||||||
|
|
||||||
The files neeeded in the folders are:
|
The files needed in the folders are:
|
||||||
|
|
||||||
include/
|
include/
|
||||||
- Leap.h
|
- Leap.h
|
||||||
|
@ -21,8 +21,8 @@ Interface has been tested with SDK versions:
|
||||||
x86/
|
x86/
|
||||||
- Leap.dll
|
- Leap.dll
|
||||||
- Leap.lib
|
- Leap.lib
|
||||||
- mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
|
- mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistributable installed)
|
||||||
- mscvcr120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
|
- mscvcr120.dll (optional if you already have the Msdev 2012 SDK redistributable installed)
|
||||||
- lipLeap.dylib
|
- lipLeap.dylib
|
||||||
libc++/
|
libc++/
|
||||||
-libLeap.dylib
|
-libLeap.dylib
|
||||||
|
@ -30,4 +30,4 @@ Interface has been tested with SDK versions:
|
||||||
You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
|
You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
|
||||||
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'leapmotion' that contains the 2 folders mentioned above (Include, Lib).
|
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'leapmotion' that contains the 2 folders mentioned above (Include, Lib).
|
||||||
|
|
||||||
2. Clear your build directory, run cmake and build, and you should be all set.
|
2. Clear your build directory, run cmake and build, and you should be all set.
|
||||||
|
|
48
interface/resources/controllers/leapmotion.json
Normal file
48
interface/resources/controllers/leapmotion.json
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"name": "Leap Motion to Standard",
|
||||||
|
"channels": [
|
||||||
|
{ "from": "LeapMotion.LeftHand", "to": "Standard.LeftHand" },
|
||||||
|
{ "from": "LeapMotion.LeftHandThumb1", "to": "Standard.LeftHandThumb1"},
|
||||||
|
{ "from": "LeapMotion.LeftHandThumb2", "to": "Standard.LeftHandThumb2"},
|
||||||
|
{ "from": "LeapMotion.LeftHandThumb3", "to": "Standard.LeftHandThumb3"},
|
||||||
|
{ "from": "LeapMotion.LeftHandThumb4", "to": "Standard.LeftHandThumb4"},
|
||||||
|
{ "from": "LeapMotion.LeftHandIndex1", "to": "Standard.LeftHandIndex1"},
|
||||||
|
{ "from": "LeapMotion.LeftHandIndex2", "to": "Standard.LeftHandIndex2"},
|
||||||
|
{ "from": "LeapMotion.LeftHandIndex3", "to": "Standard.LeftHandIndex3"},
|
||||||
|
{ "from": "LeapMotion.LeftHandIndex4", "to": "Standard.LeftHandIndex4"},
|
||||||
|
{ "from": "LeapMotion.LeftHandMiddle1", "to": "Standard.LeftHandMiddle1"},
|
||||||
|
{ "from": "LeapMotion.LeftHandMiddle2", "to": "Standard.LeftHandMiddle2"},
|
||||||
|
{ "from": "LeapMotion.LeftHandMiddle3", "to": "Standard.LeftHandMiddle3"},
|
||||||
|
{ "from": "LeapMotion.LeftHandMiddle4", "to": "Standard.LeftHandMiddle4"},
|
||||||
|
{ "from": "LeapMotion.LeftHandRing1", "to": "Standard.LeftHandRing1"},
|
||||||
|
{ "from": "LeapMotion.LeftHandRing2", "to": "Standard.LeftHandRing2"},
|
||||||
|
{ "from": "LeapMotion.LeftHandRing3", "to": "Standard.LeftHandRing3"},
|
||||||
|
{ "from": "LeapMotion.LeftHandRing4", "to": "Standard.LeftHandRing4"},
|
||||||
|
{ "from": "LeapMotion.LeftHandPinky1", "to": "Standard.LeftHandPinky1"},
|
||||||
|
{ "from": "LeapMotion.LeftHandPinky2", "to": "Standard.LeftHandPinky2"},
|
||||||
|
{ "from": "LeapMotion.LeftHandPinky3", "to": "Standard.LeftHandPinky3"},
|
||||||
|
{ "from": "LeapMotion.LeftHandPinky4", "to": "Standard.LeftHandPinky4"},
|
||||||
|
|
||||||
|
{ "from": "LeapMotion.RightHand", "to": "Standard.RightHand" },
|
||||||
|
{ "from": "LeapMotion.RightHandThumb1", "to": "Standard.RightHandThumb1"},
|
||||||
|
{ "from": "LeapMotion.RightHandThumb2", "to": "Standard.RightHandThumb2"},
|
||||||
|
{ "from": "LeapMotion.RightHandThumb3", "to": "Standard.RightHandThumb3"},
|
||||||
|
{ "from": "LeapMotion.RightHandThumb4", "to": "Standard.RightHandThumb4"},
|
||||||
|
{ "from": "LeapMotion.RightHandIndex1", "to": "Standard.RightHandIndex1"},
|
||||||
|
{ "from": "LeapMotion.RightHandIndex2", "to": "Standard.RightHandIndex2"},
|
||||||
|
{ "from": "LeapMotion.RightHandIndex3", "to": "Standard.RightHandIndex3"},
|
||||||
|
{ "from": "LeapMotion.RightHandIndex4", "to": "Standard.RightHandIndex4"},
|
||||||
|
{ "from": "LeapMotion.RightHandMiddle1", "to": "Standard.RightHandMiddle1"},
|
||||||
|
{ "from": "LeapMotion.RightHandMiddle2", "to": "Standard.RightHandMiddle2"},
|
||||||
|
{ "from": "LeapMotion.RightHandMiddle3", "to": "Standard.RightHandMiddle3"},
|
||||||
|
{ "from": "LeapMotion.RightHandMiddle4", "to": "Standard.RightHandMiddle4"},
|
||||||
|
{ "from": "LeapMotion.RightHandRing1", "to": "Standard.RightHandRing1"},
|
||||||
|
{ "from": "LeapMotion.RightHandRing2", "to": "Standard.RightHandRing2"},
|
||||||
|
{ "from": "LeapMotion.RightHandRing3", "to": "Standard.RightHandRing3"},
|
||||||
|
{ "from": "LeapMotion.RightHandRing4", "to": "Standard.RightHandRing4"},
|
||||||
|
{ "from": "LeapMotion.RightHandPinky1", "to": "Standard.RightHandPinky1"},
|
||||||
|
{ "from": "LeapMotion.RightHandPinky2", "to": "Standard.RightHandPinky2"},
|
||||||
|
{ "from": "LeapMotion.RightHandPinky3", "to": "Standard.RightHandPinky3"},
|
||||||
|
{ "from": "LeapMotion.RightHandPinky4", "to": "Standard.RightHandPinky4"}
|
||||||
|
]
|
||||||
|
}
|
|
@ -58,7 +58,48 @@
|
||||||
{ "from": "Standard.RT", "to": "Actions.RightHandClick" },
|
{ "from": "Standard.RT", "to": "Actions.RightHandClick" },
|
||||||
|
|
||||||
{ "from": "Standard.LeftHand", "to": "Actions.LeftHand" },
|
{ "from": "Standard.LeftHand", "to": "Actions.LeftHand" },
|
||||||
|
{ "from": "Standard.LeftHandThumb1", "to": "Actions.LeftHandThumb1"},
|
||||||
|
{ "from": "Standard.LeftHandThumb2", "to": "Actions.LeftHandThumb2"},
|
||||||
|
{ "from": "Standard.LeftHandThumb3", "to": "Actions.LeftHandThumb3"},
|
||||||
|
{ "from": "Standard.LeftHandThumb4", "to": "Actions.LeftHandThumb4"},
|
||||||
|
{ "from": "Standard.LeftHandIndex1", "to": "Actions.LeftHandIndex1"},
|
||||||
|
{ "from": "Standard.LeftHandIndex2", "to": "Actions.LeftHandIndex2"},
|
||||||
|
{ "from": "Standard.LeftHandIndex3", "to": "Actions.LeftHandIndex3"},
|
||||||
|
{ "from": "Standard.LeftHandIndex4", "to": "Actions.LeftHandIndex4"},
|
||||||
|
{ "from": "Standard.LeftHandMiddle1", "to": "Actions.LeftHandMiddle1"},
|
||||||
|
{ "from": "Standard.LeftHandMiddle2", "to": "Actions.LeftHandMiddle2"},
|
||||||
|
{ "from": "Standard.LeftHandMiddle3", "to": "Actions.LeftHandMiddle3"},
|
||||||
|
{ "from": "Standard.LeftHandMiddle4", "to": "Actions.LeftHandMiddle4"},
|
||||||
|
{ "from": "Standard.LeftHandRing1", "to": "Actions.LeftHandRing1"},
|
||||||
|
{ "from": "Standard.LeftHandRing2", "to": "Actions.LeftHandRing2"},
|
||||||
|
{ "from": "Standard.LeftHandRing3", "to": "Actions.LeftHandRing3"},
|
||||||
|
{ "from": "Standard.LeftHandRing4", "to": "Actions.LeftHandRing4"},
|
||||||
|
{ "from": "Standard.LeftHandPinky1", "to": "Actions.LeftHandPinky1"},
|
||||||
|
{ "from": "Standard.LeftHandPinky2", "to": "Actions.LeftHandPinky2"},
|
||||||
|
{ "from": "Standard.LeftHandPinky3", "to": "Actions.LeftHandPinky3"},
|
||||||
|
{ "from": "Standard.LeftHandPinky4", "to": "Actions.LeftHandPinky4"},
|
||||||
|
|
||||||
{ "from": "Standard.RightHand", "to": "Actions.RightHand" },
|
{ "from": "Standard.RightHand", "to": "Actions.RightHand" },
|
||||||
|
{ "from": "Standard.RightHandThumb1", "to": "Actions.RightHandThumb1"},
|
||||||
|
{ "from": "Standard.RightHandThumb2", "to": "Actions.RightHandThumb2"},
|
||||||
|
{ "from": "Standard.RightHandThumb3", "to": "Actions.RightHandThumb3"},
|
||||||
|
{ "from": "Standard.RightHandThumb4", "to": "Actions.RightHandThumb4"},
|
||||||
|
{ "from": "Standard.RightHandIndex1", "to": "Actions.RightHandIndex1"},
|
||||||
|
{ "from": "Standard.RightHandIndex2", "to": "Actions.RightHandIndex2"},
|
||||||
|
{ "from": "Standard.RightHandIndex3", "to": "Actions.RightHandIndex3"},
|
||||||
|
{ "from": "Standard.RightHandIndex4", "to": "Actions.RightHandIndex4"},
|
||||||
|
{ "from": "Standard.RightHandMiddle1", "to": "Actions.RightHandMiddle1"},
|
||||||
|
{ "from": "Standard.RightHandMiddle2", "to": "Actions.RightHandMiddle2"},
|
||||||
|
{ "from": "Standard.RightHandMiddle3", "to": "Actions.RightHandMiddle3"},
|
||||||
|
{ "from": "Standard.RightHandMiddle4", "to": "Actions.RightHandMiddle4"},
|
||||||
|
{ "from": "Standard.RightHandRing1", "to": "Actions.RightHandRing1"},
|
||||||
|
{ "from": "Standard.RightHandRing2", "to": "Actions.RightHandRing2"},
|
||||||
|
{ "from": "Standard.RightHandRing3", "to": "Actions.RightHandRing3"},
|
||||||
|
{ "from": "Standard.RightHandRing4", "to": "Actions.RightHandRing4"},
|
||||||
|
{ "from": "Standard.RightHandPinky1", "to": "Actions.RightHandPinky1"},
|
||||||
|
{ "from": "Standard.RightHandPinky2", "to": "Actions.RightHandPinky2"},
|
||||||
|
{ "from": "Standard.RightHandPinky3", "to": "Actions.RightHandPinky3"},
|
||||||
|
{ "from": "Standard.RightHandPinky4", "to": "Actions.RightHandPinky4"},
|
||||||
|
|
||||||
{ "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" },
|
{ "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" },
|
||||||
{ "from": "Standard.RightFoot", "to": "Actions.RightFoot" },
|
{ "from": "Standard.RightFoot", "to": "Actions.RightFoot" },
|
||||||
|
|
|
@ -34,36 +34,32 @@
|
||||||
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
||||||
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
||||||
|
|
||||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand", "when": [ "Application.InHMD" ] },
|
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
|
||||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand", "when": [ "Application.InHMD" ] },
|
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}],
|
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
|
||||||
"when": [ "Application.InHMD" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}],
|
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
|
||||||
"when": [ "Application.InHMD" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Hips", "to" : "Standard.Hips",
|
"from": "Vive.Hips", "to" : "Standard.Hips",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}],
|
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
|
||||||
"when": [ "Application.InHMD" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}],
|
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
|
||||||
"when": [ "Application.InHMD" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{ "from": "Vive.Head", "to" : "Standard.Head", "when": [ "Application.InHMD" ] },
|
{ "from": "Vive.Head", "to" : "Standard.Head"},
|
||||||
|
|
||||||
{ "from": "Vive.RightArm", "to" : "Standard.RightArm", "when": [ "Application.InHMD" ] },
|
{ "from": "Vive.RightArm", "to" : "Standard.RightArm"},
|
||||||
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm", "when": [ "Application.InHMD" ] }
|
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ PreferencesDialog {
|
||||||
id: root
|
id: root
|
||||||
objectName: "GeneralPreferencesDialog"
|
objectName: "GeneralPreferencesDialog"
|
||||||
title: "General Settings"
|
title: "General Settings"
|
||||||
showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect"]
|
showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"]
|
||||||
property var settings: Settings {
|
property var settings: Settings {
|
||||||
category: root.objectName
|
category: root.objectName
|
||||||
property alias x: root.x
|
property alias x: root.x
|
||||||
|
|
|
@ -25,11 +25,12 @@ Rectangle {
|
||||||
signal canceled()
|
signal canceled()
|
||||||
signal restart()
|
signal restart()
|
||||||
|
|
||||||
property int count: 3
|
property int count: 5
|
||||||
property string calibratingText: "CALIBRATING..."
|
property string calibratingText: "CALIBRATING..."
|
||||||
property string calibratingCountText: "CALIBRATION STARTING IN"
|
property string calibratingCountText: "CALIBRATION STARTING IN"
|
||||||
property string calibrationSuccess: "CALIBRATION COMPLETED"
|
property string calibrationSuccess: "CALIBRATION COMPLETED"
|
||||||
property string calibrationFailed: "CALIBRATION FAILED"
|
property string calibrationFailed: "CALIBRATION FAILED"
|
||||||
|
property string instructionText: "Please stand in a T-Pose during calibration"
|
||||||
|
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
visible: true
|
visible: true
|
||||||
|
@ -158,6 +159,15 @@ Rectangle {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
restart();
|
restart();
|
||||||
|
statusText.color = hifi.colors.blueHighlight;
|
||||||
|
statusText.text = info.calibratingCountText;
|
||||||
|
directions.text = instructionText;
|
||||||
|
countDown.visible = true;
|
||||||
|
busyIndicator.running = true;
|
||||||
|
busyRotation.from = 0
|
||||||
|
busyRotation.to = 360
|
||||||
|
busyIndicator.source = blueIndicator;
|
||||||
|
closeWindow.stop();
|
||||||
numberAnimation.stop();
|
numberAnimation.stop();
|
||||||
info.count = (timer.interval / 1000);
|
info.count = (timer.interval / 1000);
|
||||||
numberAnimation.start();
|
numberAnimation.start();
|
||||||
|
@ -178,6 +188,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function start(interval, countNumber) {
|
function start(interval, countNumber) {
|
||||||
countDown.visible = true;
|
countDown.visible = true;
|
||||||
statusText.color = hifi.colors.blueHighlight;
|
statusText.color = hifi.colors.blueHighlight;
|
||||||
|
@ -201,6 +212,7 @@ Rectangle {
|
||||||
busyIndicator.running = false;
|
busyIndicator.running = false;
|
||||||
statusText.text = info.calibrationSuccess
|
statusText.text = info.calibrationSuccess
|
||||||
statusText.color = hifi.colors.greenHighlight
|
statusText.color = hifi.colors.greenHighlight
|
||||||
|
directions.text = "SUCCESS"
|
||||||
closeWindow.start();
|
closeWindow.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -458,7 +458,7 @@ Rectangle {
|
||||||
width: glyphButton.width + calibrationText.width + padding
|
width: glyphButton.width + calibrationText.width + padding
|
||||||
height: hifi.dimensions.controlLineHeight
|
height: hifi.dimensions.controlLineHeight
|
||||||
anchors.top: bottomSeperator.bottom
|
anchors.top: bottomSeperator.bottom
|
||||||
anchors.topMargin: 10
|
anchors.topMargin: 15
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: leftMargin
|
anchors.leftMargin: leftMargin
|
||||||
|
|
||||||
|
@ -590,16 +590,24 @@ Rectangle {
|
||||||
lastConfiguration = composeConfigurationSettings();
|
lastConfiguration = composeConfigurationSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
var settings = InputConfiguration.configurationSettings(pluginName);
|
||||||
|
var data = {
|
||||||
|
"num_pucks": settings["puckCount"]
|
||||||
|
}
|
||||||
|
UserActivityLogger.logAction("mocap_ui_close_dialog", data);
|
||||||
|
}
|
||||||
|
|
||||||
HifiControls.SpinBox {
|
HifiControls.SpinBox {
|
||||||
id: timeToCalibrate
|
id: timeToCalibrate
|
||||||
width: 70
|
width: 70
|
||||||
anchors.top: calibrationButton.bottom
|
anchors.top: calibrationButton.bottom
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 20
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: leftMargin
|
anchors.leftMargin: leftMargin
|
||||||
|
|
||||||
minimumValue: 3
|
minimumValue: 5
|
||||||
value: 3
|
value: 5
|
||||||
colorScheme: hifi.colorSchemes.dark
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
|
@ -634,6 +642,57 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Separator {
|
||||||
|
id: advanceSeperator
|
||||||
|
width: parent.width
|
||||||
|
anchors.top: timeToCalibrate.bottom
|
||||||
|
anchors.topMargin: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
RalewayBold {
|
||||||
|
id: advanceSettings
|
||||||
|
|
||||||
|
text: "Advance Settings"
|
||||||
|
size: 12
|
||||||
|
|
||||||
|
color: hifi.colors.white
|
||||||
|
|
||||||
|
anchors.top: advanceSeperator.bottom
|
||||||
|
anchors.topMargin: 10
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: leftMargin
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HifiControls.CheckBox {
|
||||||
|
id: viveInDesktop
|
||||||
|
width: 15
|
||||||
|
height: 15
|
||||||
|
boxRadius: 7
|
||||||
|
|
||||||
|
anchors.top: advanceSettings.bottom
|
||||||
|
anchors.topMargin: 5
|
||||||
|
anchors.left: openVrConfiguration.left
|
||||||
|
anchors.leftMargin: leftMargin + 10
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
sendConfigurationSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RalewayBold {
|
||||||
|
id: viveDesktopText
|
||||||
|
size: 10
|
||||||
|
text: "Use vive devices in desktop mode"
|
||||||
|
color: hifi.colors.white
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
left: viveInDesktop.right
|
||||||
|
leftMargin: 5
|
||||||
|
verticalCenter: viveInDesktop.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
id: numberAnimation
|
id: numberAnimation
|
||||||
target: openVrConfiguration
|
target: openVrConfiguration
|
||||||
|
@ -641,17 +700,39 @@ Rectangle {
|
||||||
to: 0
|
to: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function logAction(action, status) {
|
||||||
|
console.log("calibrated from ui");
|
||||||
|
var data = {
|
||||||
|
"num_pucks": status["puckCount"],
|
||||||
|
"puck_configuration": status["configuration"],
|
||||||
|
"head_puck": status["head_puck"],
|
||||||
|
"hand_puck": status["hand_pucks"]
|
||||||
|
}
|
||||||
|
UserActivityLogger.logAction(action, data);
|
||||||
|
}
|
||||||
|
|
||||||
function calibrationStatusInfo(status) {
|
function calibrationStatusInfo(status) {
|
||||||
var calibrationScreen = stack.currentItem;
|
var calibrationScreen = stack.currentItem;
|
||||||
|
|
||||||
|
if (!status["UI"]) {
|
||||||
|
calibratingScreen = screen.createObject();
|
||||||
|
stack.push(calibratingScreen);
|
||||||
|
}
|
||||||
|
|
||||||
if (status["calibrated"]) {
|
if (status["calibrated"]) {
|
||||||
calibrationScreen.success();
|
calibrationScreen.success();
|
||||||
|
|
||||||
|
if (status["UI"]) {
|
||||||
|
logAction("mocap_ui_success", status);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (!status["calibrated"]) {
|
} else if (!status["calibrated"]) {
|
||||||
var uncalibrated = status["success"];
|
calibrationScreen.failure();
|
||||||
if (!uncalibrated) {
|
|
||||||
calibrationScreen.failure();
|
if (status["UI"]) {
|
||||||
|
logAction("mocap_ui_failed", status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCalibrationButton();
|
updateCalibrationButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,6 +779,7 @@ Rectangle {
|
||||||
|
|
||||||
var HmdHead = settings["HMDHead"];
|
var HmdHead = settings["HMDHead"];
|
||||||
var viveController = settings["handController"];
|
var viveController = settings["handController"];
|
||||||
|
var desktopMode = settings["desktopMode"];
|
||||||
|
|
||||||
if (HmdHead) {
|
if (HmdHead) {
|
||||||
headBox.checked = true;
|
headBox.checked = true;
|
||||||
|
@ -715,8 +797,16 @@ Rectangle {
|
||||||
handBox.checked = false;
|
handBox.checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viveInDesktop.checked = desktopMode;
|
||||||
|
|
||||||
initializeButtonState();
|
initializeButtonState();
|
||||||
updateCalibrationText();
|
updateCalibrationText();
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
"num_pucks": settings["puckCount"]
|
||||||
|
};
|
||||||
|
|
||||||
|
UserActivityLogger.logAction("mocap_ui_open_dialog", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayTrackerConfiguration(type) {
|
function displayTrackerConfiguration(type) {
|
||||||
|
@ -865,7 +955,8 @@ Rectangle {
|
||||||
var settingsObject = {
|
var settingsObject = {
|
||||||
"bodyConfiguration": trackerConfiguration,
|
"bodyConfiguration": trackerConfiguration,
|
||||||
"headConfiguration": headObject,
|
"headConfiguration": headObject,
|
||||||
"handConfiguration": handObject
|
"handConfiguration": handObject,
|
||||||
|
"desktopMode": viveInDesktop.checked
|
||||||
}
|
}
|
||||||
|
|
||||||
return settingsObject;
|
return settingsObject;
|
||||||
|
|
|
@ -94,10 +94,20 @@ StackView {
|
||||||
property bool keyboardEnabled: false
|
property bool keyboardEnabled: false
|
||||||
property bool keyboardRaised: false
|
property bool keyboardRaised: false
|
||||||
property bool punctuationMode: false
|
property bool punctuationMode: false
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
propagateComposedEvents: true
|
||||||
|
onPressed: {
|
||||||
|
parent.forceActiveFocus();
|
||||||
|
addressBarDialog.keyboardEnabled = false;
|
||||||
|
mouse.accepted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
right: parent.right
|
right: parent.right
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
@ -227,9 +237,9 @@ StackView {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!addressLine.focus || !HMD.active) {
|
addressLine.focus = true;
|
||||||
addressLine.focus = true;
|
addressLine.forceActiveFocus();
|
||||||
addressLine.forceActiveFocus();
|
if (HMD.active) {
|
||||||
addressBarDialog.keyboardEnabled = HMD.active;
|
addressBarDialog.keyboardEnabled = HMD.active;
|
||||||
}
|
}
|
||||||
tabletRoot.playButtonClickSound();
|
tabletRoot.playButtonClickSound();
|
||||||
|
|
|
@ -32,6 +32,6 @@ StackView {
|
||||||
TabletPreferencesDialog {
|
TabletPreferencesDialog {
|
||||||
id: root
|
id: root
|
||||||
objectName: "TabletGeneralPreferences"
|
objectName: "TabletGeneralPreferences"
|
||||||
showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"]
|
showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration", "Leap Motion"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QtCore/QCommandLineParser>
|
#include <QtCore/QCommandLineParser>
|
||||||
#include <QtCore/QMimeData>
|
#include <QtCore/QMimeData>
|
||||||
#include <QtCore/QThreadPool>
|
#include <QtCore/QThreadPool>
|
||||||
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
|
|
||||||
#include <QtGui/QScreen>
|
#include <QtGui/QScreen>
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
|
|
||||||
#include <gl/QOpenGLContextWrapper.h>
|
#include <gl/QOpenGLContextWrapper.h>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <shared/GlobalAppProperties.h>
|
#include <shared/GlobalAppProperties.h>
|
||||||
#include <StatTracker.h>
|
#include <StatTracker.h>
|
||||||
#include <Trace.h>
|
#include <Trace.h>
|
||||||
|
@ -145,7 +147,6 @@
|
||||||
#include "avatar/MyHead.h"
|
#include "avatar/MyHead.h"
|
||||||
#include "CrashHandler.h"
|
#include "CrashHandler.h"
|
||||||
#include "devices/DdeFaceTracker.h"
|
#include "devices/DdeFaceTracker.h"
|
||||||
#include "devices/Leapmotion.h"
|
|
||||||
#include "DiscoverabilityManager.h"
|
#include "DiscoverabilityManager.h"
|
||||||
#include "GLCanvas.h"
|
#include "GLCanvas.h"
|
||||||
#include "InterfaceDynamicFactory.h"
|
#include "InterfaceDynamicFactory.h"
|
||||||
|
@ -480,6 +481,12 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
|
static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
|
||||||
bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
|
bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
|
||||||
bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
|
bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
|
||||||
|
// get dir to use for cache
|
||||||
|
static const auto CACHE_SWITCH = "--cache";
|
||||||
|
QString cacheDir = getCmdOption(argc, const_cast<const char**>(argv), CACHE_SWITCH);
|
||||||
|
if (!cacheDir.isEmpty()) {
|
||||||
|
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
|
||||||
|
}
|
||||||
|
|
||||||
Setting::init();
|
Setting::init();
|
||||||
|
|
||||||
|
@ -1208,15 +1215,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
|
||||||
connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
QTimer* settingsTimer = new QTimer();
|
||||||
connect(&_settingsThread, SIGNAL(started()), &_settingsTimer, SLOT(start()));
|
moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{
|
||||||
connect(&_settingsThread, SIGNAL(finished()), &_settingsTimer, SLOT(stop()));
|
connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{
|
||||||
_settingsTimer.moveToThread(&_settingsThread);
|
// Disconnect the signal from the save settings
|
||||||
_settingsTimer.setSingleShot(false);
|
QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
||||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
|
// Stop the settings timer
|
||||||
_settingsThread.setPriority(QThread::LowestPriority);
|
settingsTimer->stop();
|
||||||
_settingsThread.start();
|
// Delete it (this will trigger the thread destruction
|
||||||
|
settingsTimer->deleteLater();
|
||||||
|
// Mark the settings thread as finished, so we know we can safely save in the main application
|
||||||
|
// shutdown code
|
||||||
|
_settingsGuard.trigger();
|
||||||
|
});
|
||||||
|
|
||||||
|
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
||||||
|
settingsTimer->setSingleShot(false);
|
||||||
|
settingsTimer->setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
|
||||||
|
QObject::connect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
||||||
|
}, QThread::LowestPriority);
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
|
||||||
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person.
|
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person.
|
||||||
|
@ -1644,7 +1662,7 @@ QString Application::getUserAgent() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QString userAgent;
|
QString userAgent;
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "getUserAgent", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, userAgent));
|
BLOCKING_INVOKE_METHOD(this, "getUserAgent", Q_RETURN_ARG(QString, userAgent));
|
||||||
|
|
||||||
return userAgent;
|
return userAgent;
|
||||||
}
|
}
|
||||||
|
@ -1802,11 +1820,13 @@ void Application::cleanupBeforeQuit() {
|
||||||
locationUpdateTimer.stop();
|
locationUpdateTimer.stop();
|
||||||
identityPacketTimer.stop();
|
identityPacketTimer.stop();
|
||||||
pingTimer.stop();
|
pingTimer.stop();
|
||||||
QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
|
|
||||||
|
|
||||||
// save state
|
// Wait for the settings thread to shut down, and save the settings one last time when it's safe
|
||||||
_settingsThread.quit();
|
if (_settingsGuard.wait()) {
|
||||||
saveSettings();
|
// save state
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
_window->saveGeometry();
|
_window->saveGeometry();
|
||||||
|
|
||||||
// Destroy third party processes after scripts have finished using them.
|
// Destroy third party processes after scripts have finished using them.
|
||||||
|
@ -1830,8 +1850,7 @@ void Application::cleanupBeforeQuit() {
|
||||||
|
|
||||||
// FIXME: something else is holding a reference to AudioClient,
|
// FIXME: something else is holding a reference to AudioClient,
|
||||||
// so it must be explicitly synchronously stopped here
|
// so it must be explicitly synchronously stopped here
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
|
||||||
"cleanupBeforeQuit", Qt::BlockingQueuedConnection);
|
|
||||||
|
|
||||||
// destroy Audio so it and its threads have a chance to go down safely
|
// destroy Audio so it and its threads have a chance to go down safely
|
||||||
// this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
|
// this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
|
||||||
|
@ -1886,8 +1905,6 @@ Application::~Application() {
|
||||||
// remove the NodeList from the DependencyManager
|
// remove the NodeList from the DependencyManager
|
||||||
DependencyManager::destroy<NodeList>();
|
DependencyManager::destroy<NodeList>();
|
||||||
|
|
||||||
Leapmotion::destroy();
|
|
||||||
|
|
||||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||||
steamClient->shutdown();
|
steamClient->shutdown();
|
||||||
}
|
}
|
||||||
|
@ -2154,48 +2171,74 @@ void Application::paintGL() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto displayPlugin = getActiveDisplayPlugin();
|
DisplayPluginPointer displayPlugin;
|
||||||
// FIXME not needed anymore?
|
{
|
||||||
_offscreenContext->makeCurrent();
|
PROFILE_RANGE(render, "/getActiveDisplayPlugin");
|
||||||
|
displayPlugin = getActiveDisplayPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
// If a display plugin loses it's underlying support, it
|
{
|
||||||
// needs to be able to signal us to not use it
|
PROFILE_RANGE(render, "/offscreenMakeCurrent");
|
||||||
if (!displayPlugin->beginFrameRender(_frameCount)) {
|
// FIXME not needed anymore?
|
||||||
_inPaint = false;
|
_offscreenContext->makeCurrent();
|
||||||
updateDisplayMode();
|
}
|
||||||
return;
|
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render, "/pluginBeginFrameRender");
|
||||||
|
// If a display plugin loses it's underlying support, it
|
||||||
|
// needs to be able to signal us to not use it
|
||||||
|
if (!displayPlugin->beginFrameRender(_frameCount)) {
|
||||||
|
_inPaint = false;
|
||||||
|
updateDisplayMode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the avatar with a fresh HMD pose
|
// update the avatar with a fresh HMD pose
|
||||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
{
|
||||||
|
PROFILE_RANGE(render, "/updateAvatar");
|
||||||
|
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||||
|
}
|
||||||
|
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
|
|
||||||
|
RenderArgs renderArgs;
|
||||||
{
|
{
|
||||||
QMutexLocker viewLocker(&_viewMutex);
|
PROFILE_RANGE(render, "/buildFrustrumAndArgs");
|
||||||
_viewFrustum.calculate();
|
{
|
||||||
}
|
QMutexLocker viewLocker(&_viewMutex);
|
||||||
RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
|
_viewFrustum.calculate();
|
||||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
}
|
||||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
renderArgs = RenderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
|
||||||
{
|
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||||
QMutexLocker viewLocker(&_viewMutex);
|
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||||
renderArgs.setViewFrustum(_viewFrustum);
|
{
|
||||||
|
QMutexLocker viewLocker(&_viewMutex);
|
||||||
|
renderArgs.setViewFrustum(_viewFrustum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
|
{
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
PROFILE_RANGE(render, "/resizeGL");
|
||||||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
|
||||||
resizeGL();
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
|
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||||
_gpuContext->beginFrame(getHMDSensorPose());
|
resizeGL();
|
||||||
// Reset the gpu::Context Stages
|
}
|
||||||
// Back to the default framebuffer;
|
|
||||||
gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
|
|
||||||
batch.resetStages();
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
PROFILE_RANGE(render, "/gpuContextReset");
|
||||||
|
_gpuContext->beginFrame(getHMDSensorPose());
|
||||||
|
// Reset the gpu::Context Stages
|
||||||
|
// Back to the default framebuffer;
|
||||||
|
gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
|
||||||
|
batch.resetStages();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render, "/renderOverlay");
|
||||||
PerformanceTimer perfTimer("renderOverlay");
|
PerformanceTimer perfTimer("renderOverlay");
|
||||||
// NOTE: There is no batch associated with this renderArgs
|
// NOTE: There is no batch associated with this renderArgs
|
||||||
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
||||||
|
@ -2206,114 +2249,127 @@ void Application::paintGL() {
|
||||||
|
|
||||||
glm::vec3 boomOffset;
|
glm::vec3 boomOffset;
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("CameraUpdates");
|
PROFILE_RANGE(render, "/updateCamera");
|
||||||
|
{
|
||||||
|
PerformanceTimer perfTimer("CameraUpdates");
|
||||||
|
|
||||||
auto myAvatar = getMyAvatar();
|
auto myAvatar = getMyAvatar();
|
||||||
boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
|
boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
|
||||||
|
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
||||||
cameraMenuChanged();
|
cameraMenuChanged();
|
||||||
}
|
|
||||||
|
|
||||||
// The render mode is default or mirror if the camera is in mirror mode, assigned further below
|
|
||||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
|
||||||
|
|
||||||
// Always use the default eye position, not the actual head eye position.
|
|
||||||
// Using the latter will cause the camera to wobble with idle animations,
|
|
||||||
// or with changes from the face tracker
|
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
|
||||||
if (isHMDMode()) {
|
|
||||||
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
|
||||||
_myCamera.setPosition(extractTranslation(camMat));
|
|
||||||
_myCamera.setOrientation(glm::quat_cast(camMat));
|
|
||||||
} else {
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
|
|
||||||
_myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
|
|
||||||
}
|
}
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
|
||||||
if (isHMDMode()) {
|
|
||||||
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
|
||||||
_myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
|
||||||
_myCamera.setPosition(extractTranslation(hmdWorldMat) +
|
|
||||||
myAvatar->getOrientation() * boomOffset);
|
|
||||||
} else {
|
|
||||||
_myCamera.setOrientation(myAvatar->getHead()->getOrientation());
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ _myCamera.getOrientation() * boomOffset);
|
|
||||||
} else {
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ myAvatar->getOrientation() * boomOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
|
||||||
if (isHMDMode()) {
|
|
||||||
auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
|
|
||||||
|
|
||||||
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
// The render mode is default or mirror if the camera is in mirror mode, assigned further below
|
||||||
// Mirror HMD yaw and roll
|
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||||
glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation);
|
|
||||||
mirrorHmdEulers.y = -mirrorHmdEulers.y;
|
|
||||||
mirrorHmdEulers.z = -mirrorHmdEulers.z;
|
|
||||||
glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers);
|
|
||||||
|
|
||||||
glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
|
// Always use the default eye position, not the actual head eye position.
|
||||||
|
// Using the latter will cause the camera to wobble with idle animations,
|
||||||
_myCamera.setOrientation(worldMirrorRotation);
|
// or with changes from the face tracker
|
||||||
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
|
||||||
// Mirror HMD lateral offsets
|
|
||||||
hmdOffset.x = -hmdOffset.x;
|
|
||||||
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
|
||||||
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
|
||||||
+ mirrorBodyOrientation * hmdOffset);
|
|
||||||
} else {
|
|
||||||
_myCamera.setOrientation(myAvatar->getWorldAlignedOrientation()
|
|
||||||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
|
||||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
|
||||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
|
||||||
}
|
|
||||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
|
|
||||||
EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
|
|
||||||
if (cameraEntity != nullptr) {
|
|
||||||
if (isHMDMode()) {
|
if (isHMDMode()) {
|
||||||
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
_myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
|
_myCamera.setPosition(extractTranslation(camMat));
|
||||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
_myCamera.setOrientation(glm::quat_cast(camMat));
|
||||||
_myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
|
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setOrientation(cameraEntity->getRotation());
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
|
||||||
_myCamera.setPosition(cameraEntity->getPosition());
|
_myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
|
||||||
|
}
|
||||||
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
|
if (isHMDMode()) {
|
||||||
|
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
|
_myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
||||||
|
_myCamera.setPosition(extractTranslation(hmdWorldMat) +
|
||||||
|
myAvatar->getOrientation() * boomOffset);
|
||||||
|
} else {
|
||||||
|
_myCamera.setOrientation(myAvatar->getHead()->getOrientation());
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ _myCamera.getOrientation() * boomOffset);
|
||||||
|
} else {
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ myAvatar->getOrientation() * boomOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
|
if (isHMDMode()) {
|
||||||
|
auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
|
||||||
|
|
||||||
|
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
||||||
|
// Mirror HMD yaw and roll
|
||||||
|
glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation);
|
||||||
|
mirrorHmdEulers.y = -mirrorHmdEulers.y;
|
||||||
|
mirrorHmdEulers.z = -mirrorHmdEulers.z;
|
||||||
|
glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers);
|
||||||
|
|
||||||
|
glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
|
||||||
|
|
||||||
|
_myCamera.setOrientation(worldMirrorRotation);
|
||||||
|
|
||||||
|
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||||
|
// Mirror HMD lateral offsets
|
||||||
|
hmdOffset.x = -hmdOffset.x;
|
||||||
|
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
||||||
|
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
||||||
|
+ mirrorBodyOrientation * hmdOffset);
|
||||||
|
} else {
|
||||||
|
_myCamera.setOrientation(myAvatar->getWorldAlignedOrientation()
|
||||||
|
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
|
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
||||||
|
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||||
|
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
|
}
|
||||||
|
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||||
|
} else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
|
||||||
|
EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
|
||||||
|
if (cameraEntity != nullptr) {
|
||||||
|
if (isHMDMode()) {
|
||||||
|
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
||||||
|
_myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
|
||||||
|
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||||
|
_myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
|
||||||
|
} else {
|
||||||
|
_myCamera.setOrientation(cameraEntity->getRotation());
|
||||||
|
_myCamera.setPosition(cameraEntity->getPosition());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Update camera position
|
||||||
// Update camera position
|
if (!isHMDMode()) {
|
||||||
if (!isHMDMode()) {
|
_myCamera.update(1.0f / _frameCounter.rate());
|
||||||
_myCamera.update(1.0f / _frameCounter.rate());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());
|
{
|
||||||
|
PROFILE_RANGE(render, "/updateCompositor");
|
||||||
|
getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());
|
||||||
|
}
|
||||||
|
|
||||||
// Primary rendering pass
|
gpu::FramebufferPointer finalFramebuffer;
|
||||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
QSize finalFramebufferSize;
|
||||||
const QSize size = framebufferCache->getFrameBufferSize();
|
{
|
||||||
// Final framebuffer that will be handled to the display-plugin
|
PROFILE_RANGE(render, "/getOutputFramebuffer");
|
||||||
auto finalFramebuffer = framebufferCache->getFramebuffer();
|
// Primary rendering pass
|
||||||
|
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||||
|
finalFramebufferSize = framebufferCache->getFrameBufferSize();
|
||||||
|
// Final framebuffer that will be handled to the display-plugin
|
||||||
|
finalFramebuffer = framebufferCache->getFramebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(render, "/mainRender");
|
PROFILE_RANGE(render, "/mainRender");
|
||||||
PerformanceTimer perfTimer("mainRender");
|
PerformanceTimer perfTimer("mainRender");
|
||||||
renderArgs._boomOffset = boomOffset;
|
renderArgs._boomOffset = boomOffset;
|
||||||
|
// FIXME is this ever going to be different from the size previously set in the render args
|
||||||
|
// in the overlay render?
|
||||||
// Viewport is assigned to the size of the framebuffer
|
// Viewport is assigned to the size of the framebuffer
|
||||||
renderArgs._viewport = ivec4(0, 0, size.width(), size.height());
|
renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height());
|
||||||
if (displayPlugin->isStereo()) {
|
if (displayPlugin->isStereo()) {
|
||||||
// Stereo modes will typically have a larger projection matrix overall,
|
// Stereo modes will typically have a larger projection matrix overall,
|
||||||
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
||||||
|
@ -3613,6 +3669,133 @@ bool Application::shouldPaint(float nsecsElapsed) {
|
||||||
#include <TCHAR.h>
|
#include <TCHAR.h>
|
||||||
#include <pdh.h>
|
#include <pdh.h>
|
||||||
#pragma comment(lib, "pdh.lib")
|
#pragma comment(lib, "pdh.lib")
|
||||||
|
#pragma comment(lib, "ntdll.lib")
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
enum SYSTEM_INFORMATION_CLASS {
|
||||||
|
SystemBasicInformation = 0,
|
||||||
|
SystemProcessorPerformanceInformation = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
|
||||||
|
LARGE_INTEGER IdleTime;
|
||||||
|
LARGE_INTEGER KernelTime;
|
||||||
|
LARGE_INTEGER UserTime;
|
||||||
|
LARGE_INTEGER DpcTime;
|
||||||
|
LARGE_INTEGER InterruptTime;
|
||||||
|
ULONG InterruptCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SYSTEM_BASIC_INFORMATION {
|
||||||
|
ULONG Reserved;
|
||||||
|
ULONG TimerResolution;
|
||||||
|
ULONG PageSize;
|
||||||
|
ULONG NumberOfPhysicalPages;
|
||||||
|
ULONG LowestPhysicalPageNumber;
|
||||||
|
ULONG HighestPhysicalPageNumber;
|
||||||
|
ULONG AllocationGranularity;
|
||||||
|
ULONG_PTR MinimumUserModeAddress;
|
||||||
|
ULONG_PTR MaximumUserModeAddress;
|
||||||
|
ULONG_PTR ActiveProcessorsAffinityMask;
|
||||||
|
CCHAR NumberOfProcessors;
|
||||||
|
};
|
||||||
|
|
||||||
|
NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformation(
|
||||||
|
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||||
|
_Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
|
||||||
|
_In_ ULONG SystemInformationLength,
|
||||||
|
_Out_opt_ PULONG ReturnLength
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, T& t) {
|
||||||
|
return NtQuerySystemInformation(SystemInformationClass, &t, (ULONG)sizeof(T), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, std::vector<T>& t) {
|
||||||
|
return NtQuerySystemInformation(SystemInformationClass, t.data(), (ULONG)(sizeof(T) * t.size()), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void updateValueAndDelta(std::pair<T, T>& pair, T newValue) {
|
||||||
|
auto& value = pair.first;
|
||||||
|
auto& delta = pair.second;
|
||||||
|
delta = (value != 0) ? newValue - value : 0;
|
||||||
|
value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyCpuInfo {
|
||||||
|
using ValueAndDelta = std::pair<LONGLONG, LONGLONG>;
|
||||||
|
std::string name;
|
||||||
|
ValueAndDelta kernel { 0, 0 };
|
||||||
|
ValueAndDelta user { 0, 0 };
|
||||||
|
ValueAndDelta idle { 0, 0 };
|
||||||
|
float kernelUsage { 0.0f };
|
||||||
|
float userUsage { 0.0f };
|
||||||
|
|
||||||
|
void update(const SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpuInfo) {
|
||||||
|
updateValueAndDelta(kernel, cpuInfo.KernelTime.QuadPart);
|
||||||
|
updateValueAndDelta(user, cpuInfo.UserTime.QuadPart);
|
||||||
|
updateValueAndDelta(idle, cpuInfo.IdleTime.QuadPart);
|
||||||
|
auto totalTime = kernel.second + user.second + idle.second;
|
||||||
|
if (totalTime != 0) {
|
||||||
|
kernelUsage = (FLOAT)kernel.second / totalTime;
|
||||||
|
userUsage = (FLOAT)user.second / totalTime;
|
||||||
|
} else {
|
||||||
|
kernelUsage = userUsage = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void updateCpuInformation() {
|
||||||
|
static std::once_flag once;
|
||||||
|
static SYSTEM_BASIC_INFORMATION systemInfo {};
|
||||||
|
static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpuTotals;
|
||||||
|
static std::vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> cpuInfos;
|
||||||
|
static std::vector<MyCpuInfo> myCpuInfos;
|
||||||
|
static MyCpuInfo myCpuTotals;
|
||||||
|
std::call_once(once, [&] {
|
||||||
|
NtQuerySystemInformation( SystemBasicInformation, systemInfo);
|
||||||
|
cpuInfos.resize(systemInfo.NumberOfProcessors);
|
||||||
|
myCpuInfos.resize(systemInfo.NumberOfProcessors);
|
||||||
|
for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) {
|
||||||
|
myCpuInfos[i].name = "cpu." + std::to_string(i);
|
||||||
|
}
|
||||||
|
myCpuTotals.name = "cpu.total";
|
||||||
|
});
|
||||||
|
NtQuerySystemInformation(SystemProcessorPerformanceInformation, cpuInfos);
|
||||||
|
|
||||||
|
// Zero the CPU totals.
|
||||||
|
memset(&cpuTotals, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
|
||||||
|
for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) {
|
||||||
|
auto& cpuInfo = cpuInfos[i];
|
||||||
|
// KernelTime includes IdleTime.
|
||||||
|
cpuInfo.KernelTime.QuadPart -= cpuInfo.IdleTime.QuadPart;
|
||||||
|
|
||||||
|
// Update totals
|
||||||
|
cpuTotals.IdleTime.QuadPart += cpuInfo.IdleTime.QuadPart;
|
||||||
|
cpuTotals.KernelTime.QuadPart += cpuInfo.KernelTime.QuadPart;
|
||||||
|
cpuTotals.UserTime.QuadPart += cpuInfo.UserTime.QuadPart;
|
||||||
|
|
||||||
|
// Update friendly structure
|
||||||
|
auto& myCpuInfo = myCpuInfos[i];
|
||||||
|
myCpuInfo.update(cpuInfo);
|
||||||
|
PROFILE_COUNTER(app, myCpuInfo.name.c_str(), {
|
||||||
|
{ "kernel", myCpuInfo.kernelUsage },
|
||||||
|
{ "user", myCpuInfo.userUsage }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
myCpuTotals.update(cpuTotals);
|
||||||
|
PROFILE_COUNTER(app, myCpuTotals.name.c_str(), {
|
||||||
|
{ "kernel", myCpuTotals.kernelUsage },
|
||||||
|
{ "user", myCpuTotals.userUsage }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
|
static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
|
||||||
static int numProcessors;
|
static int numProcessors;
|
||||||
|
@ -3665,6 +3848,26 @@ void getCpuUsage(vec3& systemAndUser) {
|
||||||
systemAndUser.z = (float)counterVal.doubleValue;
|
systemAndUser.z = (float)counterVal.doubleValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupCpuMonitorThread() {
|
||||||
|
initCpuUsage();
|
||||||
|
auto cpuMonitorThread = QThread::currentThread();
|
||||||
|
|
||||||
|
QTimer* timer = new QTimer();
|
||||||
|
timer->setInterval(50);
|
||||||
|
QObject::connect(timer, &QTimer::timeout, [] {
|
||||||
|
updateCpuInformation();
|
||||||
|
vec3 kernelUserAndSystem;
|
||||||
|
getCpuUsage(kernelUserAndSystem);
|
||||||
|
PROFILE_COUNTER(app, "cpuProcess", { { "system", kernelUserAndSystem.x }, { "user", kernelUserAndSystem.y } });
|
||||||
|
PROFILE_COUNTER(app, "cpuSystem", { { "system", kernelUserAndSystem.z } });
|
||||||
|
});
|
||||||
|
QObject::connect(cpuMonitorThread, &QThread::finished, [=] {
|
||||||
|
timer->deleteLater();
|
||||||
|
cpuMonitorThread->deleteLater();
|
||||||
|
});
|
||||||
|
timer->start();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -3685,15 +3888,17 @@ void Application::idle(float nsecsElapsed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
// If tracing is enabled then monitor the CPU in a separate thread
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
std::call_once(once, [] {
|
std::call_once(once, [&] {
|
||||||
initCpuUsage();
|
if (trace_app().isDebugEnabled()) {
|
||||||
|
QThread* cpuMonitorThread = new QThread(qApp);
|
||||||
|
cpuMonitorThread->setObjectName("cpuMonitorThread");
|
||||||
|
QObject::connect(cpuMonitorThread, &QThread::started, [this] { setupCpuMonitorThread(); });
|
||||||
|
QObject::connect(qApp, &QCoreApplication::aboutToQuit, cpuMonitorThread, &QThread::quit);
|
||||||
|
cpuMonitorThread->start();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
vec3 kernelUserAndSystem;
|
|
||||||
getCpuUsage(kernelUserAndSystem);
|
|
||||||
PROFILE_COUNTER(app, "cpuProcess", { { "system", kernelUserAndSystem.x }, { "user", kernelUserAndSystem.y } });
|
|
||||||
PROFILE_COUNTER(app, "cpuSystem", { { "system", kernelUserAndSystem.z } });
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -4055,8 +4260,6 @@ void Application::init() {
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Loaded settings";
|
qCDebug(interfaceapp) << "Loaded settings";
|
||||||
|
|
||||||
Leapmotion::init();
|
|
||||||
|
|
||||||
// fire off an immediate domain-server check in now that settings are loaded
|
// fire off an immediate domain-server check in now that settings are loaded
|
||||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||||
|
|
||||||
|
@ -4520,7 +4723,6 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("devices");
|
PerformanceTimer perfTimer("devices");
|
||||||
DeviceTracker::updateAll();
|
|
||||||
|
|
||||||
FaceTracker* tracker = getSelectedFaceTracker();
|
FaceTracker* tracker = getSelectedFaceTracker();
|
||||||
if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) {
|
if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) {
|
||||||
|
@ -4589,8 +4791,6 @@ void Application::update(float deltaTime) {
|
||||||
keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData);
|
keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
_controllerScriptingInterface->updateInputControllers();
|
|
||||||
|
|
||||||
// Transfer the user inputs to the driveKeys
|
// Transfer the user inputs to the driveKeys
|
||||||
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
||||||
myAvatar->clearDriveKeys();
|
myAvatar->clearDriveKeys();
|
||||||
|
@ -4615,6 +4815,31 @@ void Application::update(float deltaTime) {
|
||||||
auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;
|
auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;
|
||||||
myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix));
|
myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix));
|
||||||
|
|
||||||
|
// If have previously done finger poses or there are new valid finger poses, update finger pose values. This so that if
|
||||||
|
// fingers are not being controlled, finger joints are not updated in MySkeletonModel.
|
||||||
|
// Assumption: Finger poses are either all present and valid or not present at all; thus can test just one joint.
|
||||||
|
MyAvatar::FingerPosesMap leftHandFingerPoses;
|
||||||
|
if (myAvatar->getLeftHandFingerControllerPosesInSensorFrame().size() > 0
|
||||||
|
|| userInputMapper->getPoseState(controller::Action::LEFT_HAND_THUMB1).isValid()) {
|
||||||
|
for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) {
|
||||||
|
leftHandFingerPoses[i] = {
|
||||||
|
userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
|
||||||
|
userInputMapper->getActionName((controller::Action)i)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MyAvatar::FingerPosesMap rightHandFingerPoses;
|
||||||
|
if (myAvatar->getRightHandFingerControllerPosesInSensorFrame().size() > 0
|
||||||
|
|| userInputMapper->getPoseState(controller::Action::RIGHT_HAND_THUMB1).isValid()) {
|
||||||
|
for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) {
|
||||||
|
rightHandFingerPoses[i] = {
|
||||||
|
userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
|
||||||
|
userInputMapper->getActionName((controller::Action)i)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myAvatar->setFingerControllerPosesInSensorFrame(leftHandFingerPoses, rightHandFingerPoses);
|
||||||
|
|
||||||
controller::Pose leftFootPose = userInputMapper->getPoseState(controller::Action::LEFT_FOOT);
|
controller::Pose leftFootPose = userInputMapper->getPoseState(controller::Action::LEFT_FOOT);
|
||||||
controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT);
|
controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT);
|
||||||
myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix));
|
myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix));
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtWidgets/QUndoStack>
|
#include <QtWidgets/QUndoStack>
|
||||||
|
|
||||||
|
#include <ThreadHelpers.h>
|
||||||
#include <AbstractScriptingServicesInterface.h>
|
#include <AbstractScriptingServicesInterface.h>
|
||||||
#include <AbstractViewStateInterface.h>
|
#include <AbstractViewStateInterface.h>
|
||||||
#include <EntityEditPacketSender.h>
|
#include <EntityEditPacketSender.h>
|
||||||
|
@ -298,7 +299,6 @@ public:
|
||||||
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
||||||
QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; }
|
QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; }
|
||||||
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
||||||
void setCacheOverrideDir(const QString& dirName) { _cacheDir = dirName; }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void svoImportRequested(const QString& url);
|
void svoImportRequested(const QString& url);
|
||||||
|
@ -596,8 +596,7 @@ private:
|
||||||
|
|
||||||
bool _notifiedPacketVersionMismatchThisDomain;
|
bool _notifiedPacketVersionMismatchThisDomain;
|
||||||
|
|
||||||
QThread _settingsThread;
|
ConditionalGuard _settingsGuard;
|
||||||
QTimer _settingsTimer;
|
|
||||||
|
|
||||||
GLCanvas* _glWidget{ nullptr };
|
GLCanvas* _glWidget{ nullptr };
|
||||||
|
|
||||||
|
@ -691,6 +690,5 @@ private:
|
||||||
QUrl _avatarOverrideUrl;
|
QUrl _avatarOverrideUrl;
|
||||||
bool _saveAvatarOverrideUrl { false };
|
bool _saveAvatarOverrideUrl { false };
|
||||||
|
|
||||||
QString _cacheDir;
|
|
||||||
};
|
};
|
||||||
#endif // hifi_Application_h
|
#endif // hifi_Application_h
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <OffscreenUi.h>
|
#include <OffscreenUi.h>
|
||||||
|
@ -24,6 +25,8 @@
|
||||||
#include "AvatarBookmarks.h"
|
#include "AvatarBookmarks.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
|
||||||
|
#include "QVariantGLM.h"
|
||||||
|
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
AvatarBookmarks::AvatarBookmarks() {
|
AvatarBookmarks::AvatarBookmarks() {
|
||||||
|
@ -58,16 +61,48 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarBookmark);
|
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarBookmark);
|
||||||
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
||||||
|
|
||||||
Bookmarks::setupMenus(menubar, menu);
|
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) {
|
||||||
|
addBookmarkToMenu(menubar, it.key(), it.value());
|
||||||
|
}
|
||||||
|
|
||||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::changeToBookmarkedAvatar() {
|
void AvatarBookmarks::changeToBookmarkedAvatar() {
|
||||||
QAction* action = qobject_cast<QAction*>(sender());
|
QAction* action = qobject_cast<QAction*>(sender());
|
||||||
const QString& address = action->data().toString();
|
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
myAvatar->useFullAvatarURL(address);
|
|
||||||
|
|
||||||
|
|
||||||
|
if (action->data().type() == QVariant::String) {
|
||||||
|
// TODO: Phase this out eventually.
|
||||||
|
// Legacy avatar bookmark.
|
||||||
|
|
||||||
|
myAvatar->useFullAvatarURL(action->data().toString());
|
||||||
|
qCDebug(interfaceapp) << " Using Legacy V1 Avatar Bookmark ";
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const QMap<QString, QVariant> bookmark = action->data().toMap();
|
||||||
|
// Not magic value. This is the current made version, and if it changes this interpreter should be updated to
|
||||||
|
// handle the new one separately.
|
||||||
|
// This is where the avatar bookmark entry is parsed. If adding new Value, make sure to have backward compatability with previous
|
||||||
|
if (bookmark.value(ENTRY_VERSION) == 3) {
|
||||||
|
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
||||||
|
myAvatar->useFullAvatarURL(avatarUrl);
|
||||||
|
qCDebug(interfaceapp) << "Avatar On " << avatarUrl;
|
||||||
|
const QList<QVariant>& attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList<QVariant>()).toList();
|
||||||
|
|
||||||
|
qCDebug(interfaceapp) << "Attach " << attachments;
|
||||||
|
myAvatar->setAttachmentsVariant(attachments);
|
||||||
|
|
||||||
|
const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
||||||
|
myAvatar->setAvatarScale(qScale);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qCDebug(interfaceapp) << " Bookmark entry does not match client version, make sure client has a handler for the new AvatarBookmark";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::addBookmark() {
|
void AvatarBookmarks::addBookmark() {
|
||||||
|
@ -83,13 +118,23 @@ void AvatarBookmarks::addBookmark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
const QString& bookmarkAddress = myAvatar->getSkeletonModelURL().toString();
|
|
||||||
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
|
const QString& avatarUrl = myAvatar->getSkeletonModelURL().toString();
|
||||||
|
const QVariant& avatarScale = myAvatar->getAvatarScale();
|
||||||
|
|
||||||
|
// If Avatar attachments ever change, this is where to update them, when saving remember to also append to AVATAR_BOOKMARK_VERSION
|
||||||
|
QVariantMap *bookmark = new QVariantMap;
|
||||||
|
bookmark->insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
||||||
|
bookmark->insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||||
|
bookmark->insert(ENTRY_AVATAR_SCALE, avatarScale);
|
||||||
|
bookmark->insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
|
||||||
|
|
||||||
|
Bookmarks::addBookmarkToFile(bookmarkName, *bookmark);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) {
|
void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) {
|
||||||
QAction* changeAction = _bookmarksMenu->newAction();
|
QAction* changeAction = _bookmarksMenu->newAction();
|
||||||
changeAction->setData(address);
|
changeAction->setData(bookmark);
|
||||||
connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar()));
|
connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar()));
|
||||||
if (!_isMenuSorted) {
|
if (!_isMenuSorted) {
|
||||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
||||||
|
|
|
@ -21,18 +21,23 @@ class AvatarBookmarks: public Bookmarks, public Dependency {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AvatarBookmarks();
|
AvatarBookmarks();
|
||||||
|
|
||||||
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void addBookmark();
|
void addBookmark();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
|
void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) override;
|
||||||
void readFromFile();
|
void readFromFile() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||||
|
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||||
|
const QString ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
||||||
|
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
||||||
|
const QString ENTRY_VERSION = "version";
|
||||||
|
|
||||||
|
const int AVATAR_BOOKMARK_VERSION = 3;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void changeToBookmarkedAvatar();
|
void changeToBookmarkedAvatar();
|
||||||
|
|
|
@ -28,19 +28,6 @@ Bookmarks::Bookmarks() :
|
||||||
_isMenuSorted(false)
|
_isMenuSorted(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
|
||||||
// Enable/Disable menus as needed
|
|
||||||
enableMenuItems(_bookmarks.count() > 0);
|
|
||||||
|
|
||||||
// Load Bookmarks
|
|
||||||
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) {
|
|
||||||
QString bookmarkName = it.key();
|
|
||||||
QString bookmarkAddress = it.value().toString();
|
|
||||||
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bookmarks::deleteBookmark() {
|
void Bookmarks::deleteBookmark() {
|
||||||
QStringList bookmarkList;
|
QStringList bookmarkList;
|
||||||
QList<QAction*> menuItems = _bookmarksMenu->actions();
|
QList<QAction*> menuItems = _bookmarksMenu->actions();
|
||||||
|
@ -67,7 +54,7 @@ void Bookmarks::deleteBookmark() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress) {
|
void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QVariant& bookmark) {
|
||||||
Menu* menubar = Menu::getInstance();
|
Menu* menubar = Menu::getInstance();
|
||||||
if (contains(bookmarkName)) {
|
if (contains(bookmarkName)) {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
@ -75,7 +62,6 @@ void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bo
|
||||||
"The bookmark name you entered already exists in your list.",
|
"The bookmark name you entered already exists in your list.",
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
|
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
|
||||||
|
|
||||||
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
|
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
|
||||||
if (result != QMessageBox::Yes) {
|
if (result != QMessageBox::Yes) {
|
||||||
return;
|
return;
|
||||||
|
@ -83,19 +69,20 @@ void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bo
|
||||||
removeBookmarkFromMenu(menubar, bookmarkName);
|
removeBookmarkFromMenu(menubar, bookmarkName);
|
||||||
}
|
}
|
||||||
|
|
||||||
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
|
addBookmarkToMenu(menubar, bookmarkName, bookmark);
|
||||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
insert(bookmarkName, bookmark); // Overwrites any item with the same bookmarkName.
|
||||||
enableMenuItems(true);
|
enableMenuItems(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bookmarks::insert(const QString& name, const QString& address) {
|
void Bookmarks::insert(const QString& name, const QVariant& bookmark) {
|
||||||
_bookmarks.insert(name, address);
|
_bookmarks.insert(name, bookmark);
|
||||||
|
|
||||||
if (contains(name)) {
|
if (contains(name)) {
|
||||||
qCDebug(interfaceapp) << "Added bookmark:" << name << "," << address;
|
qCDebug(interfaceapp) << "Added bookmark:" << name;
|
||||||
persistToFile();
|
persistToFile();
|
||||||
} else {
|
}
|
||||||
qWarning() << "Couldn't add bookmark: " << name << "," << address;
|
else {
|
||||||
|
qWarning() << "Couldn't add bookmark: " << name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,18 +27,20 @@ class Bookmarks: public QObject {
|
||||||
public:
|
public:
|
||||||
Bookmarks();
|
Bookmarks();
|
||||||
|
|
||||||
virtual void setupMenus(Menu* menubar, MenuWrapper* menu);
|
virtual void setupMenus(Menu* menubar, MenuWrapper* menu) = 0;
|
||||||
QString addressForBookmark(const QString& name) const;
|
QString addressForBookmark(const QString& name) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress);
|
void addBookmarkToFile(const QString& bookmarkName, const QVariant& bookmark);
|
||||||
virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0;
|
virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) = 0;
|
||||||
void enableMenuItems(bool enabled);
|
void enableMenuItems(bool enabled);
|
||||||
void readFromFile();
|
virtual void readFromFile();
|
||||||
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
|
void insert(const QString& name, const QVariant& address); // Overwrites any existing entry with same name.
|
||||||
void sortActions(Menu* menubar, MenuWrapper* menu);
|
void sortActions(Menu* menubar, MenuWrapper* menu);
|
||||||
int getMenuItemLocation(QList<QAction*> actions, const QString& name) const;
|
int getMenuItemLocation(QList<QAction*> actions, const QString& name) const;
|
||||||
|
|
||||||
|
bool contains(const QString& name) const;
|
||||||
|
|
||||||
QVariantMap _bookmarks; // { name: url, ... }
|
QVariantMap _bookmarks; // { name: url, ... }
|
||||||
QPointer<MenuWrapper> _bookmarksMenu;
|
QPointer<MenuWrapper> _bookmarksMenu;
|
||||||
QPointer<QAction> _deleteBookmarksAction;
|
QPointer<QAction> _deleteBookmarksAction;
|
||||||
|
@ -50,7 +52,6 @@ protected slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void remove(const QString& name);
|
void remove(const QString& name);
|
||||||
bool contains(const QString& name) const;
|
|
||||||
static bool sortOrder(QAction* a, QAction* b);
|
static bool sortOrder(QAction* a, QAction* b);
|
||||||
|
|
||||||
void persistToFile();
|
void persistToFile();
|
||||||
|
|
|
@ -41,13 +41,25 @@ void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
|
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
|
||||||
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
||||||
|
|
||||||
Bookmarks::setupMenus(menubar, menu);
|
// Legacy Location to Bookmark.
|
||||||
|
|
||||||
|
// Enable/Disable menus as needed
|
||||||
|
enableMenuItems(_bookmarks.count() > 0);
|
||||||
|
|
||||||
|
// Load Bookmarks
|
||||||
|
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) {
|
||||||
|
QString bookmarkName = it.key();
|
||||||
|
QString bookmarkAddress = it.value().toString();
|
||||||
|
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||||
|
}
|
||||||
|
|
||||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocationBookmarks::setHomeLocation() {
|
void LocationBookmarks::setHomeLocation() {
|
||||||
auto addressManager = DependencyManager::get<AddressManager>();
|
auto addressManager = DependencyManager::get<AddressManager>();
|
||||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||||
|
|
||||||
Bookmarks::addBookmarkToFile(HOME_BOOKMARK, bookmarkAddress);
|
Bookmarks::addBookmarkToFile(HOME_BOOKMARK, bookmarkAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +86,7 @@ void LocationBookmarks::addBookmark() {
|
||||||
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
|
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) {
|
void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& address) {
|
||||||
QAction* teleportAction = _bookmarksMenu->newAction();
|
QAction* teleportAction = _bookmarksMenu->newAction();
|
||||||
teleportAction->setData(address);
|
teleportAction->setData(address);
|
||||||
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
|
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
|
||||||
|
@ -85,4 +97,4 @@ void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, co
|
||||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
|
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
|
||||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ public slots:
|
||||||
void addBookmark();
|
void addBookmark();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
|
void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& address) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString LOCATIONBOOKMARKS_FILENAME = "bookmarks.json";
|
const QString LOCATIONBOOKMARKS_FILENAME = "bookmarks.json";
|
||||||
|
|
|
@ -566,9 +566,6 @@ Menu::Menu() {
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
|
||||||
avatar.get(), SLOT(setEnableDebugDrawHandControllers(bool)));
|
avatar.get(), SLOT(setEnableDebugDrawHandControllers(bool)));
|
||||||
|
|
||||||
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
|
|
||||||
addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
|
|
||||||
|
|
||||||
// Developer > Entities >>>
|
// Developer > Entities >>>
|
||||||
MenuWrapper* entitiesOptionsMenu = developerMenu->addMenu("Entities");
|
MenuWrapper* entitiesOptionsMenu = developerMenu->addMenu("Entities");
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,6 @@ namespace MenuOption {
|
||||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||||
const QString IndependentMode = "Independent Mode";
|
const QString IndependentMode = "Independent Mode";
|
||||||
const QString ActionMotorControl = "Enable Default Motor Control";
|
const QString ActionMotorControl = "Enable Default Motor Control";
|
||||||
const QString LeapMotionOnHMD = "Leap Motion on HMD";
|
|
||||||
const QString LoadScript = "Open and Run Script File...";
|
const QString LoadScript = "Open and Run Script File...";
|
||||||
const QString LoadScriptURL = "Open and Run Script from URL...";
|
const QString LoadScriptURL = "Open and Run Script from URL...";
|
||||||
const QString LodTools = "LOD Tools";
|
const QString LodTools = "LOD Tools";
|
||||||
|
|
|
@ -79,6 +79,7 @@ public:
|
||||||
|
|
||||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||||
batch.disableContextStereo();
|
batch.disableContextStereo();
|
||||||
|
batch.disableContextViewCorrection();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto srcViewFrustum = args->getViewFrustum();
|
auto srcViewFrustum = args->getViewFrustum();
|
||||||
|
@ -112,6 +113,7 @@ public:
|
||||||
|
|
||||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||||
batch.restoreContextStereo();
|
batch.restoreContextStereo();
|
||||||
|
batch.restoreContextViewCorrection();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
@ -482,7 +483,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay&
|
||||||
const QScriptValue& avatarIdsToDiscard) {
|
const QScriptValue& avatarIdsToDiscard) {
|
||||||
RayToAvatarIntersectionResult result;
|
RayToAvatarIntersectionResult result;
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarManager*>(this), "findRayIntersection", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarManager*>(this), "findRayIntersection",
|
||||||
Q_RETURN_ARG(RayToAvatarIntersectionResult, result),
|
Q_RETURN_ARG(RayToAvatarIntersectionResult, result),
|
||||||
Q_ARG(const PickRay&, ray),
|
Q_ARG(const PickRay&, ray),
|
||||||
Q_ARG(const QScriptValue&, avatarIdsToInclude),
|
Q_ARG(const QScriptValue&, avatarIdsToInclude),
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <scripting/HMDScriptingInterface.h>
|
#include <scripting/HMDScriptingInterface.h>
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
#include <AddressManager.h>
|
#include <AddressManager.h>
|
||||||
|
@ -897,7 +898,7 @@ void MyAvatar::restoreAnimation() {
|
||||||
QStringList MyAvatar::getAnimationRoles() {
|
QStringList MyAvatar::getAnimationRoles() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(this, "getAnimationRoles", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QStringList, result));
|
BLOCKING_INVOKE_METHOD(this, "getAnimationRoles", Q_RETURN_ARG(QStringList, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return _skeletonModel->getRig().getAnimationRoles();
|
return _skeletonModel->getRig().getAnimationRoles();
|
||||||
|
@ -1368,7 +1369,7 @@ void MyAvatar::resetFullAvatarURL() {
|
||||||
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
|
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
|
||||||
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "useFullAvatarURL",
|
||||||
Q_ARG(const QUrl&, fullAvatarURL),
|
Q_ARG(const QUrl&, fullAvatarURL),
|
||||||
Q_ARG(const QString&, modelName));
|
Q_ARG(const QString&, modelName));
|
||||||
return;
|
return;
|
||||||
|
@ -1394,7 +1395,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
|
||||||
|
|
||||||
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "setAttachmentData", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1455,6 +1456,19 @@ controller::Pose MyAvatar::getRightHandControllerPoseInAvatarFrame() const {
|
||||||
return getRightHandControllerPoseInWorldFrame().transform(invAvatarMatrix);
|
return getRightHandControllerPoseInWorldFrame().transform(invAvatarMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setFingerControllerPosesInSensorFrame(const FingerPosesMap& left, const FingerPosesMap& right) {
|
||||||
|
_leftHandFingerPosesInSensorFramceCache.set(left);
|
||||||
|
_rightHandFingerPosesInSensorFramceCache.set(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar::FingerPosesMap MyAvatar::getLeftHandFingerControllerPosesInSensorFrame() const {
|
||||||
|
return _leftHandFingerPosesInSensorFramceCache.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar::FingerPosesMap MyAvatar::getRightHandFingerControllerPosesInSensorFrame() const {
|
||||||
|
return _rightHandFingerPosesInSensorFramceCache.get();
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right) {
|
void MyAvatar::setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right) {
|
||||||
_leftFootControllerPoseInSensorFrameCache.set(left);
|
_leftFootControllerPoseInSensorFrameCache.set(left);
|
||||||
_rightFootControllerPoseInSensorFrameCache.set(right);
|
_rightFootControllerPoseInSensorFrameCache.set(right);
|
||||||
|
@ -1620,7 +1634,8 @@ void MyAvatar::prepareForPhysicsSimulation() {
|
||||||
_characterController.setParentVelocity(parentVelocity);
|
_characterController.setParentVelocity(parentVelocity);
|
||||||
|
|
||||||
_characterController.setPositionAndOrientation(getPosition(), getOrientation());
|
_characterController.setPositionAndOrientation(getPosition(), getOrientation());
|
||||||
if (qApp->isHMDMode()) {
|
auto headPose = getHeadControllerPoseInAvatarFrame();
|
||||||
|
if (headPose.isValid()) {
|
||||||
_follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix, hasDriveInput());
|
_follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix, hasDriveInput());
|
||||||
} else {
|
} else {
|
||||||
_follow.deactivate();
|
_follow.deactivate();
|
||||||
|
@ -2358,7 +2373,7 @@ bool MyAvatar::safeLanding(const glm::vec3& position) {
|
||||||
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(this, "safeLanding", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result), Q_ARG(const glm::vec3&, position));
|
BLOCKING_INVOKE_METHOD(this, "safeLanding", Q_RETURN_ARG(bool, result), Q_ARG(const glm::vec3&, position));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
glm::vec3 better;
|
glm::vec3 better;
|
||||||
|
@ -2524,6 +2539,21 @@ bool MyAvatar::getFlyingEnabled() {
|
||||||
return _enableFlying;
|
return _enableFlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Public interface for targetscale
|
||||||
|
float MyAvatar::getAvatarScale() {
|
||||||
|
return getTargetScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setAvatarScale(float val) {
|
||||||
|
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "setAvatarScale", Q_ARG(float, val));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTargetScale(val);
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::setCollisionsEnabled(bool enabled) {
|
void MyAvatar::setCollisionsEnabled(bool enabled) {
|
||||||
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
|
|
|
@ -366,7 +366,7 @@ public:
|
||||||
float getDriveKey(DriveKeys key) const;
|
float getDriveKey(DriveKeys key) const;
|
||||||
Q_INVOKABLE float getRawDriveKey(DriveKeys key) const;
|
Q_INVOKABLE float getRawDriveKey(DriveKeys key) const;
|
||||||
void relayDriveKeysToCharacterController();
|
void relayDriveKeysToCharacterController();
|
||||||
|
|
||||||
Q_INVOKABLE void disableDriveKey(DriveKeys key);
|
Q_INVOKABLE void disableDriveKey(DriveKeys key);
|
||||||
Q_INVOKABLE void enableDriveKey(DriveKeys key);
|
Q_INVOKABLE void enableDriveKey(DriveKeys key);
|
||||||
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;
|
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;
|
||||||
|
@ -474,6 +474,11 @@ public:
|
||||||
controller::Pose getLeftHandControllerPoseInAvatarFrame() const;
|
controller::Pose getLeftHandControllerPoseInAvatarFrame() const;
|
||||||
controller::Pose getRightHandControllerPoseInAvatarFrame() const;
|
controller::Pose getRightHandControllerPoseInAvatarFrame() const;
|
||||||
|
|
||||||
|
typedef std::map<int, std::pair<controller::Pose, QString>> FingerPosesMap;
|
||||||
|
void setFingerControllerPosesInSensorFrame(const FingerPosesMap& left, const FingerPosesMap& right);
|
||||||
|
FingerPosesMap getLeftHandFingerControllerPosesInSensorFrame() const;
|
||||||
|
FingerPosesMap getRightHandFingerControllerPosesInSensorFrame() const;
|
||||||
|
|
||||||
void setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right);
|
void setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right);
|
||||||
controller::Pose getLeftFootControllerPoseInSensorFrame() const;
|
controller::Pose getLeftFootControllerPoseInSensorFrame() const;
|
||||||
controller::Pose getRightFootControllerPoseInSensorFrame() const;
|
controller::Pose getRightFootControllerPoseInSensorFrame() const;
|
||||||
|
@ -512,6 +517,9 @@ public:
|
||||||
Q_INVOKABLE void setFlyingEnabled(bool enabled);
|
Q_INVOKABLE void setFlyingEnabled(bool enabled);
|
||||||
Q_INVOKABLE bool getFlyingEnabled();
|
Q_INVOKABLE bool getFlyingEnabled();
|
||||||
|
|
||||||
|
Q_INVOKABLE float getAvatarScale();
|
||||||
|
Q_INVOKABLE void setAvatarScale(float scale);
|
||||||
|
|
||||||
Q_INVOKABLE void setCollisionsEnabled(bool enabled);
|
Q_INVOKABLE void setCollisionsEnabled(bool enabled);
|
||||||
Q_INVOKABLE bool getCollisionsEnabled();
|
Q_INVOKABLE bool getCollisionsEnabled();
|
||||||
Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated
|
Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated
|
||||||
|
@ -788,13 +796,15 @@ private:
|
||||||
// These are stored in SENSOR frame
|
// These are stored in SENSOR frame
|
||||||
ThreadSafeValueCache<controller::Pose> _leftHandControllerPoseInSensorFrameCache { controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _leftHandControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
ThreadSafeValueCache<controller::Pose> _rightHandControllerPoseInSensorFrameCache { controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _rightHandControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
ThreadSafeValueCache<controller::Pose> _leftFootControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<FingerPosesMap> _leftHandFingerPosesInSensorFramceCache { };
|
||||||
ThreadSafeValueCache<controller::Pose> _rightFootControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<FingerPosesMap> _rightHandFingerPosesInSensorFramceCache { };
|
||||||
ThreadSafeValueCache<controller::Pose> _hipsControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _leftFootControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
ThreadSafeValueCache<controller::Pose> _spine2ControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _rightFootControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
ThreadSafeValueCache<controller::Pose> _headControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _hipsControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
ThreadSafeValueCache<controller::Pose> _leftArmControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _spine2ControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
ThreadSafeValueCache<controller::Pose> _rightArmControllerPoseInSensorFrameCache{ controller::Pose() };
|
ThreadSafeValueCache<controller::Pose> _headControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
|
ThreadSafeValueCache<controller::Pose> _leftArmControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
|
ThreadSafeValueCache<controller::Pose> _rightArmControllerPoseInSensorFrameCache { controller::Pose() };
|
||||||
|
|
||||||
bool _hmdLeanRecenterEnabled = true;
|
bool _hmdLeanRecenterEnabled = true;
|
||||||
AnimPose _prePhysicsRoomPose;
|
AnimPose _prePhysicsRoomPose;
|
||||||
|
|
|
@ -96,7 +96,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
params.controllerPoses[Rig::ControllerType_RightArm] = AnimPose::identity;
|
params.controllerPoses[Rig::ControllerType_RightArm] = AnimPose::identity;
|
||||||
params.controllerActiveFlags[Rig::ControllerType_RightArm] = false;
|
params.controllerActiveFlags[Rig::ControllerType_RightArm] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto avatarLeftArmPose = myAvatar->getLeftArmControllerPoseInAvatarFrame();
|
auto avatarLeftArmPose = myAvatar->getLeftArmControllerPoseInAvatarFrame();
|
||||||
if (avatarLeftArmPose.isValid()) {
|
if (avatarLeftArmPose.isValid()) {
|
||||||
AnimPose pose(avatarLeftArmPose.getRotation(), avatarLeftArmPose.getTranslation());
|
AnimPose pose(avatarLeftArmPose.getRotation(), avatarLeftArmPose.getTranslation());
|
||||||
|
@ -174,5 +174,50 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||||
|
|
||||||
_rig.updateFromEyeParameters(eyeParams);
|
_rig.updateFromEyeParameters(eyeParams);
|
||||||
|
|
||||||
|
updateFingers(myAvatar->getLeftHandFingerControllerPosesInSensorFrame());
|
||||||
|
updateFingers(myAvatar->getRightHandFingerControllerPosesInSensorFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MySkeletonModel::updateFingers(const MyAvatar::FingerPosesMap& fingerPoses) {
|
||||||
|
// Assumes that finger poses are kept in order in the poses map.
|
||||||
|
|
||||||
|
if (fingerPoses.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto posesMapItr = fingerPoses.begin();
|
||||||
|
|
||||||
|
bool isLeftHand = posesMapItr->first < (int)controller::Action::RIGHT_HAND_THUMB1;
|
||||||
|
|
||||||
|
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
||||||
|
auto handPose = isLeftHand
|
||||||
|
? myAvatar->getLeftHandControllerPoseInSensorFrame()
|
||||||
|
: myAvatar->getRightHandControllerPoseInSensorFrame();
|
||||||
|
auto handJointRotation = handPose.getRotation();
|
||||||
|
|
||||||
|
bool isHandValid = handPose.isValid();
|
||||||
|
bool isFingerValid = false;
|
||||||
|
glm::quat previousJointRotation;
|
||||||
|
|
||||||
|
while (posesMapItr != fingerPoses.end()) {
|
||||||
|
auto jointName = posesMapItr->second.second;
|
||||||
|
if (isHandValid && jointName.right(1) == "1") {
|
||||||
|
isFingerValid = posesMapItr->second.first.isValid();
|
||||||
|
previousJointRotation = handJointRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHandValid && isFingerValid) {
|
||||||
|
auto thisJointRotation = posesMapItr->second.first.getRotation();
|
||||||
|
const float CONTROLLER_PRIORITY = 2.0f;
|
||||||
|
_rig.setJointRotation(_rig.indexOfJoint(jointName), true, glm::inverse(previousJointRotation) * thisJointRotation,
|
||||||
|
CONTROLLER_PRIORITY);
|
||||||
|
previousJointRotation = thisJointRotation;
|
||||||
|
} else {
|
||||||
|
_rig.clearJointAnimationPriority(_rig.indexOfJoint(jointName));
|
||||||
|
}
|
||||||
|
|
||||||
|
posesMapItr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define hifi_MySkeletonModel_h
|
#define hifi_MySkeletonModel_h
|
||||||
|
|
||||||
#include <avatars-renderer/SkeletonModel.h>
|
#include <avatars-renderer/SkeletonModel.h>
|
||||||
|
#include "MyAvatar.h"
|
||||||
|
|
||||||
/// A skeleton loaded from a model.
|
/// A skeleton loaded from a model.
|
||||||
class MySkeletonModel : public SkeletonModel {
|
class MySkeletonModel : public SkeletonModel {
|
||||||
|
@ -21,6 +22,9 @@ private:
|
||||||
public:
|
public:
|
||||||
MySkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr);
|
MySkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr);
|
||||||
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateFingers(const MyAvatar::FingerPosesMap& fingerPoses);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MySkeletonModel_h
|
#endif // hifi_MySkeletonModel_h
|
||||||
|
|
|
@ -1,246 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Sam Cake on 6/2/2014
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Leapmotion.h"
|
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
|
||||||
|
|
||||||
#include "Menu.h"
|
|
||||||
|
|
||||||
const int PALMROOT_NUM_JOINTS = 3;
|
|
||||||
const int FINGER_NUM_JOINTS = 4;
|
|
||||||
const int HAND_NUM_JOINTS = FINGER_NUM_JOINTS*5+PALMROOT_NUM_JOINTS;
|
|
||||||
|
|
||||||
const DeviceTracker::Name Leapmotion::NAME = "Leapmotion";
|
|
||||||
|
|
||||||
// find the index of a joint from
|
|
||||||
// the side: true = right
|
|
||||||
// the finger & the bone:
|
|
||||||
// finger in [0..4] : bone in [0..3] a finger phalange
|
|
||||||
// [-1] up the hand branch : bone in [0..2] <=> [ hand, forearm, arm]
|
|
||||||
MotionTracker::Index evalJointIndex(bool isRightSide, int finger, int bone) {
|
|
||||||
|
|
||||||
MotionTracker::Index offset = 1 // start after root
|
|
||||||
+ (int(isRightSide) * HAND_NUM_JOINTS) // then offset for side
|
|
||||||
+ PALMROOT_NUM_JOINTS; // then add the arm/forearm/hand chain
|
|
||||||
if (finger >= 0) {
|
|
||||||
// from there go down in the correct finger and bone
|
|
||||||
return offset + (finger * FINGER_NUM_JOINTS) + bone;
|
|
||||||
} else {
|
|
||||||
// or go back up for the correct root bone
|
|
||||||
return offset - 1 - bone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Leapmotion::init() {
|
|
||||||
DeviceTracker* device = DeviceTracker::getDevice(NAME);
|
|
||||||
|
|
||||||
if (!device) {
|
|
||||||
// create a new Leapmotion and register it
|
|
||||||
Leapmotion* leap = new Leapmotion();
|
|
||||||
DeviceTracker::registerDevice(NAME, leap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Leapmotion::destroy() {
|
|
||||||
DeviceTracker::destroyDevice(NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
Leapmotion* Leapmotion::getInstance() {
|
|
||||||
DeviceTracker* device = DeviceTracker::getDevice(NAME);
|
|
||||||
if (!device) {
|
|
||||||
// create a new Leapmotion and register it
|
|
||||||
device = new Leapmotion();
|
|
||||||
DeviceTracker::registerDevice(NAME, device);
|
|
||||||
}
|
|
||||||
return dynamic_cast< Leapmotion* > (device);
|
|
||||||
}
|
|
||||||
|
|
||||||
Leapmotion::Leapmotion() :
|
|
||||||
MotionTracker(),
|
|
||||||
_active(false)
|
|
||||||
{
|
|
||||||
// Create the Leapmotion joint hierarchy
|
|
||||||
std::vector< Semantic > sides;
|
|
||||||
sides.push_back("joint_L_");
|
|
||||||
sides.push_back("joint_R_");
|
|
||||||
|
|
||||||
std::vector< Semantic > rootBones;
|
|
||||||
rootBones.push_back("elbow");
|
|
||||||
rootBones.push_back("wrist");
|
|
||||||
rootBones.push_back("hand");
|
|
||||||
|
|
||||||
std::vector< Semantic > fingers;
|
|
||||||
fingers.push_back("thumb");
|
|
||||||
fingers.push_back("index");
|
|
||||||
fingers.push_back("middle");
|
|
||||||
fingers.push_back("ring");
|
|
||||||
fingers.push_back("pinky");
|
|
||||||
|
|
||||||
std::vector< Semantic > fingerBones;
|
|
||||||
fingerBones.push_back("1");
|
|
||||||
fingerBones.push_back("2");
|
|
||||||
fingerBones.push_back("3");
|
|
||||||
fingerBones.push_back("4");
|
|
||||||
|
|
||||||
std::vector< Index > palms;
|
|
||||||
for (unsigned int s = 0; s < sides.size(); s++) {
|
|
||||||
Index rootJoint = 0;
|
|
||||||
for (unsigned int rb = 0; rb < rootBones.size(); rb++) {
|
|
||||||
rootJoint = addJoint(sides[s] + rootBones[rb], rootJoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// capture the hand index for debug
|
|
||||||
palms.push_back(rootJoint);
|
|
||||||
|
|
||||||
for (unsigned int f = 0; f < fingers.size(); f++) {
|
|
||||||
for (unsigned int b = 0; b < fingerBones.size(); b++) {
|
|
||||||
rootJoint = addJoint(sides[s] + fingers[f] + fingerBones[b], rootJoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LEAPMOTION
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::LeapMotionOnHMD)) {
|
|
||||||
_controller.setPolicyFlags(Leap::Controller::POLICY_OPTIMIZE_HMD);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Leapmotion::~Leapmotion() {
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LEAPMOTION
|
|
||||||
glm::quat quatFromLeapBase(float sideSign, const Leap::Matrix& basis) {
|
|
||||||
|
|
||||||
// fix the handness to right and always...
|
|
||||||
glm::vec3 xAxis = glm::normalize(sideSign * glm::vec3(basis.xBasis.x, basis.xBasis.y, basis.xBasis.z));
|
|
||||||
glm::vec3 yAxis = glm::normalize(glm::vec3(basis.yBasis.x, basis.yBasis.y, basis.yBasis.z));
|
|
||||||
glm::vec3 zAxis = glm::normalize(glm::vec3(basis.zBasis.x, basis.zBasis.y, basis.zBasis.z));
|
|
||||||
|
|
||||||
xAxis = glm::normalize(glm::cross(yAxis, zAxis));
|
|
||||||
|
|
||||||
glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis)));
|
|
||||||
return orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 vec3FromLeapVector(const Leap::Vector& vec) {
|
|
||||||
return glm::vec3(vec.x * METERS_PER_MILLIMETER, vec.y * METERS_PER_MILLIMETER, vec.z * METERS_PER_MILLIMETER);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Leapmotion::update() {
|
|
||||||
#ifdef HAVE_LEAPMOTION
|
|
||||||
bool wasActive = _active;
|
|
||||||
_active = _controller.isConnected();
|
|
||||||
|
|
||||||
if (_active || wasActive) {
|
|
||||||
// Go through all the joints and increment their counter since last update.
|
|
||||||
// Increment all counters once after controller first becomes inactive so that each joint reports itself as inactive.
|
|
||||||
// TODO C++11 for (auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) {
|
|
||||||
for (JointTracker::Vector::iterator jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) {
|
|
||||||
(*jointIt).tickNewFrame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_active) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the most recent frame and report some basic information
|
|
||||||
const Leap::Frame frame = _controller.frame();
|
|
||||||
static int64_t lastFrameID = -1;
|
|
||||||
int64_t newFrameID = frame.id();
|
|
||||||
|
|
||||||
// If too soon then exit
|
|
||||||
if (lastFrameID >= newFrameID)
|
|
||||||
return;
|
|
||||||
|
|
||||||
glm::vec3 delta(0.0f);
|
|
||||||
glm::quat handOri;
|
|
||||||
if (!frame.hands().isEmpty()) {
|
|
||||||
for (int handNum = 0; handNum < frame.hands().count(); handNum++) {
|
|
||||||
|
|
||||||
const Leap::Hand hand = frame.hands()[handNum];
|
|
||||||
int side = (hand.isRight() ? 1 : -1);
|
|
||||||
|
|
||||||
JointTracker* parentJointTracker = _jointsArray.data();
|
|
||||||
|
|
||||||
|
|
||||||
int rootBranchIndex = -1;
|
|
||||||
|
|
||||||
Leap::Arm arm = hand.arm();
|
|
||||||
if (arm.isValid()) {
|
|
||||||
glm::quat ori = quatFromLeapBase(float(side), arm.basis());
|
|
||||||
glm::vec3 pos = vec3FromLeapVector(arm.elbowPosition());
|
|
||||||
JointTracker* elbow = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 2)); // 2 is the index of the elbow joint
|
|
||||||
elbow->editAbsFrame().setTranslation(pos);
|
|
||||||
elbow->editAbsFrame().setRotation(ori);
|
|
||||||
elbow->updateLocFromAbsTransform(parentJointTracker);
|
|
||||||
elbow->activeFrame();
|
|
||||||
parentJointTracker = elbow;
|
|
||||||
|
|
||||||
pos = vec3FromLeapVector(arm.wristPosition());
|
|
||||||
JointTracker* wrist = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 1)); // 1 is the index of the wrist joint
|
|
||||||
wrist->editAbsFrame().setTranslation(pos);
|
|
||||||
wrist->editAbsFrame().setRotation(ori);
|
|
||||||
wrist->updateLocFromAbsTransform(parentJointTracker);
|
|
||||||
wrist->activeFrame();
|
|
||||||
parentJointTracker = wrist;
|
|
||||||
}
|
|
||||||
|
|
||||||
JointTracker* palmJoint = NULL;
|
|
||||||
{
|
|
||||||
glm::vec3 pos = vec3FromLeapVector(hand.palmPosition());
|
|
||||||
glm::quat ori = quatFromLeapBase(float(side), hand.basis());
|
|
||||||
|
|
||||||
palmJoint = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 0)); // 0 is the index of the palm joint
|
|
||||||
palmJoint->editAbsFrame().setTranslation(pos);
|
|
||||||
palmJoint->editAbsFrame().setRotation(ori);
|
|
||||||
palmJoint->updateLocFromAbsTransform(parentJointTracker);
|
|
||||||
palmJoint->activeFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the hand has any fingers
|
|
||||||
const Leap::FingerList fingers = hand.fingers();
|
|
||||||
if (!fingers.isEmpty()) {
|
|
||||||
// For every fingers in the list
|
|
||||||
for (int i = 0; i < fingers.count(); ++i) {
|
|
||||||
// Reset the parent joint to the palmJoint for every finger traversal
|
|
||||||
parentJointTracker = palmJoint;
|
|
||||||
|
|
||||||
// surprisingly, Leap::Finger::Type start at 0 for thumb a until 4 for the pinky
|
|
||||||
Index fingerIndex = evalJointIndex((side > 0), int(fingers[i].type()), 0);
|
|
||||||
|
|
||||||
// let's update the finger's joints
|
|
||||||
for (int b = 0; b < FINGER_NUM_JOINTS; b++) {
|
|
||||||
Leap::Bone::Type type = Leap::Bone::Type(b + Leap::Bone::TYPE_METACARPAL);
|
|
||||||
Leap::Bone bone = fingers[i].bone(type);
|
|
||||||
JointTracker* ljointTracker = editJointTracker(fingerIndex + b);
|
|
||||||
if (bone.isValid()) {
|
|
||||||
Leap::Vector bp = bone.nextJoint();
|
|
||||||
|
|
||||||
ljointTracker->editAbsFrame().setTranslation(vec3FromLeapVector(bp));
|
|
||||||
ljointTracker->editAbsFrame().setRotation(quatFromLeapBase(float(side), bone.basis()));
|
|
||||||
ljointTracker->updateLocFromAbsTransform(parentJointTracker);
|
|
||||||
ljointTracker->activeFrame();
|
|
||||||
}
|
|
||||||
parentJointTracker = ljointTracker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastFrameID = newFrameID;
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Sam Cake on 6/2/2014
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_Leapmotion_h
|
|
||||||
#define hifi_Leapmotion_h
|
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
|
|
||||||
#include <trackers/MotionTracker.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_LEAPMOTION
|
|
||||||
#include <Leap.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Handles interaction with the Leapmotion skeleton tracking suit.
|
|
||||||
class Leapmotion : public MotionTracker {
|
|
||||||
public:
|
|
||||||
static const Name NAME;
|
|
||||||
|
|
||||||
static void init();
|
|
||||||
static void destroy();
|
|
||||||
|
|
||||||
/// Leapmotion MotionTracker factory
|
|
||||||
static Leapmotion* getInstance();
|
|
||||||
|
|
||||||
bool isActive() const { return _active; }
|
|
||||||
|
|
||||||
virtual void update() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Leapmotion();
|
|
||||||
virtual ~Leapmotion();
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifdef HAVE_LEAPMOTION
|
|
||||||
Leap::Listener _listener;
|
|
||||||
Leap::Controller _controller;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool _active;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_Leapmotion_h
|
|
|
@ -101,7 +101,7 @@ int main(int argc, const char* argv[]) {
|
||||||
if (allowMultipleInstances) {
|
if (allowMultipleInstances) {
|
||||||
instanceMightBeRunning = false;
|
instanceMightBeRunning = false;
|
||||||
}
|
}
|
||||||
// this needs to be done here in main, as the mechanism for setting the
|
// this needs to be done here in main, as the mechanism for setting the
|
||||||
// scripts directory appears not to work. See the bug report
|
// scripts directory appears not to work. See the bug report
|
||||||
// https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine
|
// https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine
|
||||||
if (parser.isSet(overrideScriptsPathOption)) {
|
if (parser.isSet(overrideScriptsPathOption)) {
|
||||||
|
@ -111,20 +111,6 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser.isSet(overrideAppLocalDataPathOption)) {
|
|
||||||
// get dir to use for cache
|
|
||||||
QString cacheDir = parser.value(overrideAppLocalDataPathOption);
|
|
||||||
if (!cacheDir.isEmpty()) {
|
|
||||||
// tell everyone to use the right cache location
|
|
||||||
//
|
|
||||||
// this handles data8 and prepared
|
|
||||||
DependencyManager::get<ResourceManager>()->setCacheDir(cacheDir);
|
|
||||||
|
|
||||||
// this does the ktx_cache
|
|
||||||
PathUtils::getAppLocalDataPath(cacheDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instanceMightBeRunning) {
|
if (instanceMightBeRunning) {
|
||||||
// Try to connect and send message to existing interface instance
|
// Try to connect and send message to existing interface instance
|
||||||
QLocalSocket socket;
|
QLocalSocket socket;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "Audio.h"
|
#include "Audio.h"
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "AudioClient.h"
|
#include "AudioClient.h"
|
||||||
#include "ui/AvatarInputs.h"
|
#include "ui/AvatarInputs.h"
|
||||||
|
@ -49,27 +51,22 @@ float Audio::loudnessToLevel(float loudness) {
|
||||||
Audio::Audio() : _devices(_contextIsHMD) {
|
Audio::Audio() : _devices(_contextIsHMD) {
|
||||||
auto client = DependencyManager::get<AudioClient>().data();
|
auto client = DependencyManager::get<AudioClient>().data();
|
||||||
connect(client, &AudioClient::muteToggled, this, &Audio::onMutedChanged);
|
connect(client, &AudioClient::muteToggled, this, &Audio::onMutedChanged);
|
||||||
|
connect(client, &AudioClient::noiseReductionChanged, this, &Audio::onNoiseReductionChanged);
|
||||||
connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged);
|
connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged);
|
||||||
|
connect(client, &AudioClient::inputVolumeChanged, this, &Audio::onInputVolumeChanged);
|
||||||
connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged);
|
connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged);
|
||||||
connect(&_devices._inputs, &AudioDeviceList::deviceChanged, this, &Audio::onInputChanged);
|
|
||||||
enableNoiseReduction(enableNoiseReductionSetting.get());
|
enableNoiseReduction(enableNoiseReductionSetting.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::setMuted(bool isMuted) {
|
void Audio::setMuted(bool isMuted) {
|
||||||
if (_isMuted != isMuted) {
|
if (_isMuted != isMuted) {
|
||||||
auto client = DependencyManager::get<AudioClient>().data();
|
auto client = DependencyManager::get<AudioClient>().data();
|
||||||
QMetaObject::invokeMethod(client, "toggleMute", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(client, "toggleMute");
|
||||||
|
|
||||||
_isMuted = isMuted;
|
|
||||||
emit mutedChanged(_isMuted);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::onMutedChanged() {
|
void Audio::onMutedChanged() {
|
||||||
auto client = DependencyManager::get<AudioClient>().data();
|
bool isMuted = DependencyManager::get<AudioClient>()->isMuted();
|
||||||
bool isMuted;
|
|
||||||
QMetaObject::invokeMethod(client, "isMuted", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isMuted));
|
|
||||||
|
|
||||||
if (_isMuted != isMuted) {
|
if (_isMuted != isMuted) {
|
||||||
_isMuted = isMuted;
|
_isMuted = isMuted;
|
||||||
emit mutedChanged(_isMuted);
|
emit mutedChanged(_isMuted);
|
||||||
|
@ -79,11 +76,16 @@ void Audio::onMutedChanged() {
|
||||||
void Audio::enableNoiseReduction(bool enable) {
|
void Audio::enableNoiseReduction(bool enable) {
|
||||||
if (_enableNoiseReduction != enable) {
|
if (_enableNoiseReduction != enable) {
|
||||||
auto client = DependencyManager::get<AudioClient>().data();
|
auto client = DependencyManager::get<AudioClient>().data();
|
||||||
QMetaObject::invokeMethod(client, "setNoiseReduction", Qt::BlockingQueuedConnection, Q_ARG(bool, enable));
|
QMetaObject::invokeMethod(client, "setNoiseReduction", Q_ARG(bool, enable));
|
||||||
|
|
||||||
enableNoiseReductionSetting.set(enable);
|
enableNoiseReductionSetting.set(enable);
|
||||||
_enableNoiseReduction = enable;
|
}
|
||||||
emit noiseReductionChanged(enable);
|
}
|
||||||
|
|
||||||
|
void Audio::onNoiseReductionChanged() {
|
||||||
|
bool noiseReductionEnabled = DependencyManager::get<AudioClient>()->isNoiseReductionEnabled();
|
||||||
|
if (_enableNoiseReduction != noiseReductionEnabled) {
|
||||||
|
_enableNoiseReduction = noiseReductionEnabled;
|
||||||
|
emit noiseReductionChanged(_enableNoiseReduction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,19 +95,11 @@ void Audio::setInputVolume(float volume) {
|
||||||
|
|
||||||
if (_inputVolume != volume) {
|
if (_inputVolume != volume) {
|
||||||
auto client = DependencyManager::get<AudioClient>().data();
|
auto client = DependencyManager::get<AudioClient>().data();
|
||||||
QMetaObject::invokeMethod(client, "setInputVolume", Qt::BlockingQueuedConnection, Q_ARG(float, volume));
|
QMetaObject::invokeMethod(client, "setInputVolume", Q_ARG(float, volume));
|
||||||
|
|
||||||
_inputVolume = volume;
|
|
||||||
emit inputVolumeChanged(_inputVolume);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// different audio input devices may have different volumes
|
void Audio::onInputVolumeChanged(float volume) {
|
||||||
void Audio::onInputChanged() {
|
|
||||||
auto client = DependencyManager::get<AudioClient>().data();
|
|
||||||
float volume;
|
|
||||||
QMetaObject::invokeMethod(client, "getInputVolume", Qt::BlockingQueuedConnection, Q_RETURN_ARG(float, volume));
|
|
||||||
|
|
||||||
if (_inputVolume != volume) {
|
if (_inputVolume != volume) {
|
||||||
_inputVolume = volume;
|
_inputVolume = volume;
|
||||||
emit inputVolumeChanged(_inputVolume);
|
emit inputVolumeChanged(_inputVolume);
|
||||||
|
|
|
@ -62,9 +62,12 @@ signals:
|
||||||
void contextChanged(const QString& context);
|
void contextChanged(const QString& context);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onMutedChanged();
|
|
||||||
void onContextChanged();
|
void onContextChanged();
|
||||||
void onInputChanged();
|
|
||||||
|
private slots:
|
||||||
|
void onMutedChanged();
|
||||||
|
void onNoiseReductionChanged();
|
||||||
|
void onInputVolumeChanged(float volume);
|
||||||
void onInputLoudnessChanged(float loudness);
|
void onInputLoudnessChanged(float loudness);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
#include "AudioDevices.h"
|
#include "AudioDevices.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
@ -71,22 +73,14 @@ bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, i
|
||||||
bool AudioDeviceList::setDevice(int row, bool fromUser) {
|
bool AudioDeviceList::setDevice(int row, bool fromUser) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
auto& device = _devices[row];
|
auto& device = _devices[row];
|
||||||
|
_userSelection = fromUser;
|
||||||
|
|
||||||
// skip if already selected
|
// skip if already selected
|
||||||
if (!device.selected) {
|
if (!device.selected) {
|
||||||
auto client = DependencyManager::get<AudioClient>();
|
auto client = DependencyManager::get<AudioClient>();
|
||||||
QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection,
|
QMetaObject::invokeMethod(client.data(), "switchAudioDevice",
|
||||||
Q_RETURN_ARG(bool, success),
|
|
||||||
Q_ARG(QAudio::Mode, _mode),
|
Q_ARG(QAudio::Mode, _mode),
|
||||||
Q_ARG(const QAudioDeviceInfo&, device.info));
|
Q_ARG(const QAudioDeviceInfo&, device.info));
|
||||||
|
|
||||||
if (success) {
|
|
||||||
device.selected = true;
|
|
||||||
if (fromUser) {
|
|
||||||
emit deviceSelected(device.info, _selectedDevice);
|
|
||||||
}
|
|
||||||
emit deviceChanged(device.info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
|
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
|
||||||
|
@ -135,12 +129,12 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) {
|
void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) {
|
||||||
|
auto oldDevice = _selectedDevice;
|
||||||
_selectedDevice = device;
|
_selectedDevice = device;
|
||||||
QModelIndex index;
|
QModelIndex index;
|
||||||
|
|
||||||
for (auto i = 0; i < _devices.size(); ++i) {
|
for (auto i = 0; i < _devices.size(); ++i) {
|
||||||
AudioDevice& device = _devices[i];
|
AudioDevice& device = _devices[i];
|
||||||
|
|
||||||
if (device.selected && device.info != _selectedDevice) {
|
if (device.selected && device.info != _selectedDevice) {
|
||||||
device.selected = false;
|
device.selected = false;
|
||||||
} else if (device.info == _selectedDevice) {
|
} else if (device.info == _selectedDevice) {
|
||||||
|
@ -149,6 +143,11 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_userSelection) {
|
||||||
|
_userSelection = false;
|
||||||
|
emit deviceSelected(_selectedDevice, oldDevice);
|
||||||
|
}
|
||||||
|
|
||||||
emit deviceChanged(_selectedDevice);
|
emit deviceChanged(_selectedDevice);
|
||||||
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
|
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ private:
|
||||||
|
|
||||||
static QHash<int, QByteArray> _roles;
|
static QHash<int, QByteArray> _roles;
|
||||||
static Qt::ItemFlags _flags;
|
static Qt::ItemFlags _flags;
|
||||||
|
bool _userSelection { false };
|
||||||
QAudio::Mode _mode;
|
QAudio::Mode _mode;
|
||||||
QAudioDeviceInfo _selectedDevice;
|
QAudioDeviceInfo _selectedDevice;
|
||||||
QList<AudioDevice> _devices;
|
QList<AudioDevice> _devices;
|
||||||
|
|
|
@ -8,9 +8,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
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "ClipboardScriptingInterface.h"
|
#include "ClipboardScriptingInterface.h"
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
ClipboardScriptingInterface::ClipboardScriptingInterface() {
|
ClipboardScriptingInterface::ClipboardScriptingInterface() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +27,7 @@ float ClipboardScriptingInterface::getClipboardContentsLargestDimension() {
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
||||||
bool retVal;
|
bool retVal;
|
||||||
QMetaObject::invokeMethod(qApp, "exportEntities", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(qApp, "exportEntities",
|
||||||
Q_RETURN_ARG(bool, retVal),
|
Q_RETURN_ARG(bool, retVal),
|
||||||
Q_ARG(const QString&, filename),
|
Q_ARG(const QString&, filename),
|
||||||
Q_ARG(const QVector<EntityItemID>&, entityIDs));
|
Q_ARG(const QVector<EntityItemID>&, entityIDs));
|
||||||
|
@ -33,7 +36,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, const
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) {
|
bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) {
|
||||||
bool retVal;
|
bool retVal;
|
||||||
QMetaObject::invokeMethod(qApp, "exportEntities", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(qApp, "exportEntities",
|
||||||
Q_RETURN_ARG(bool, retVal),
|
Q_RETURN_ARG(bool, retVal),
|
||||||
Q_ARG(const QString&, filename),
|
Q_ARG(const QString&, filename),
|
||||||
Q_ARG(float, x),
|
Q_ARG(float, x),
|
||||||
|
@ -45,7 +48,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, float
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
||||||
bool retVal;
|
bool retVal;
|
||||||
QMetaObject::invokeMethod(qApp, "importEntities", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(qApp, "importEntities",
|
||||||
Q_RETURN_ARG(bool, retVal),
|
Q_RETURN_ARG(bool, retVal),
|
||||||
Q_ARG(const QString&, filename));
|
Q_ARG(const QString&, filename));
|
||||||
return retVal;
|
return retVal;
|
||||||
|
@ -53,7 +56,7 @@ bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
||||||
|
|
||||||
QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(glm::vec3 position) {
|
QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(glm::vec3 position) {
|
||||||
QVector<EntityItemID> retVal;
|
QVector<EntityItemID> retVal;
|
||||||
QMetaObject::invokeMethod(qApp, "pasteEntities", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(qApp, "pasteEntities",
|
||||||
Q_RETURN_ARG(QVector<EntityItemID>, retVal),
|
Q_RETURN_ARG(QVector<EntityItemID>, retVal),
|
||||||
Q_ARG(float, position.x),
|
Q_ARG(float, position.x),
|
||||||
Q_ARG(float, position.y),
|
Q_ARG(float, position.y),
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <EntityItemID.h>
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @namespace Clipboard
|
* @namespace Clipboard
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include <plugins/PluginManager.h>
|
#include <plugins/PluginManager.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include <trackers/MotionTracker.h>
|
|
||||||
|
|
||||||
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
|
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
|
||||||
if (event->type() == HFActionEvent::startType()) {
|
if (event->type() == HFActionEvent::startType()) {
|
||||||
|
@ -97,86 +96,6 @@ QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
||||||
return qRectToVariant(rect);
|
return qRectToVariant(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
|
||||||
// This is where we retrieve the Device Tracker category and then the sub tracker within it
|
|
||||||
auto icIt = _inputControllers.find(0);
|
|
||||||
if (icIt != _inputControllers.end()) {
|
|
||||||
return (*icIt).second.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for device
|
|
||||||
DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString());
|
|
||||||
if (deviceID < 0) {
|
|
||||||
deviceID = 0;
|
|
||||||
}
|
|
||||||
// TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion)
|
|
||||||
// in the near future we need to change that to a real mapping between the devices and the deviceName
|
|
||||||
// ALso we need to expand the spec so we can fall back on the "default" controller per categories
|
|
||||||
|
|
||||||
if (deviceID >= 0) {
|
|
||||||
// TODO here again the assumption it's the LeapMotion and so it's a MOtionTracker, this would need to be changed to support different types of devices
|
|
||||||
MotionTracker* motionTracker = dynamic_cast< MotionTracker* > (DeviceTracker::getDevice(deviceID));
|
|
||||||
if (motionTracker) {
|
|
||||||
MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString());
|
|
||||||
if (trackerID >= 0) {
|
|
||||||
controller::InputController::Pointer inputController = std::make_shared<InputController>(deviceID, trackerID, this);
|
|
||||||
controller::InputController::Key key = inputController->getKey();
|
|
||||||
_inputControllers.insert(InputControllerMap::value_type(key, inputController));
|
|
||||||
return inputController.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerScriptingInterface::releaseInputController(controller::InputController* input) {
|
|
||||||
_inputControllers.erase(input->getKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllerScriptingInterface::updateInputControllers() {
|
|
||||||
for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) {
|
|
||||||
(*it).second->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) :
|
|
||||||
_deviceTrackerId(deviceTrackerId),
|
|
||||||
_subTrackerId(subTrackerId),
|
|
||||||
_isActive(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputController::update() {
|
|
||||||
_isActive = false;
|
|
||||||
|
|
||||||
// TODO for now the InputController is only supporting a JointTracker from a MotionTracker
|
|
||||||
MotionTracker* motionTracker = dynamic_cast< MotionTracker*> (DeviceTracker::getDevice(_deviceTrackerId));
|
|
||||||
if (motionTracker) {
|
|
||||||
if ((int)_subTrackerId < motionTracker->numJointTrackers()) {
|
|
||||||
const MotionTracker::JointTracker* joint = motionTracker->getJointTracker(_subTrackerId);
|
|
||||||
|
|
||||||
if (joint->isActive()) {
|
|
||||||
joint->getAbsFrame().getTranslation(_eventCache.absTranslation);
|
|
||||||
joint->getAbsFrame().getRotation(_eventCache.absRotation);
|
|
||||||
joint->getLocFrame().getTranslation(_eventCache.locTranslation);
|
|
||||||
joint->getLocFrame().getRotation(_eventCache.locRotation);
|
|
||||||
|
|
||||||
_isActive = true;
|
|
||||||
//emit spatialEvent(_eventCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int INPUTCONTROLLER_KEY_DEVICE_OFFSET = 16;
|
|
||||||
const unsigned int INPUTCONTROLLER_KEY_DEVICE_MASK = 16;
|
|
||||||
|
|
||||||
InputController::Key InputController::getKey() const {
|
|
||||||
return (((_deviceTrackerId & INPUTCONTROLLER_KEY_DEVICE_MASK) << INPUTCONTROLLER_KEY_DEVICE_OFFSET) | _subTrackerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); }
|
void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); }
|
||||||
void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); }
|
void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); }
|
||||||
|
|
||||||
|
|
|
@ -25,38 +25,6 @@
|
||||||
#include <WheelEvent.h>
|
#include <WheelEvent.h>
|
||||||
class ScriptEngine;
|
class ScriptEngine;
|
||||||
|
|
||||||
class PalmData;
|
|
||||||
|
|
||||||
class InputController : public controller::InputController {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
InputController(int deviceTrackerId, int subTrackerId, QObject* parent = NULL);
|
|
||||||
|
|
||||||
virtual void update() override;
|
|
||||||
virtual Key getKey() const override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
virtual bool isActive() const override { return _isActive; }
|
|
||||||
virtual glm::vec3 getAbsTranslation() const override { return _eventCache.absTranslation; }
|
|
||||||
virtual glm::quat getAbsRotation() const override { return _eventCache.absRotation; }
|
|
||||||
virtual glm::vec3 getLocTranslation() const override { return _eventCache.locTranslation; }
|
|
||||||
virtual glm::quat getLocRotation() const override { return _eventCache.locRotation; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int _deviceTrackerId;
|
|
||||||
uint _subTrackerId;
|
|
||||||
|
|
||||||
// cache for the spatial
|
|
||||||
SpatialEvent _eventCache;
|
|
||||||
bool _isActive;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// handles scripting of input controller commands from JS
|
/// handles scripting of input controller commands from JS
|
||||||
class ControllerScriptingInterface : public controller::ScriptingInterface {
|
class ControllerScriptingInterface : public controller::ScriptingInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -86,8 +54,6 @@ public:
|
||||||
bool isJoystickCaptured(int joystickIndex) const;
|
bool isJoystickCaptured(int joystickIndex) const;
|
||||||
bool areEntityClicksCaptured() const;
|
bool areEntityClicksCaptured() const;
|
||||||
|
|
||||||
void updateInputControllers();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
virtual void captureKeyEvents(const KeyEvent& event);
|
virtual void captureKeyEvents(const KeyEvent& event);
|
||||||
|
@ -102,10 +68,6 @@ public slots:
|
||||||
virtual glm::vec2 getViewportDimensions() const;
|
virtual glm::vec2 getViewportDimensions() const;
|
||||||
virtual QVariant getRecommendedOverlayRect() const;
|
virtual QVariant getRecommendedOverlayRect() const;
|
||||||
|
|
||||||
/// Factory to create an InputController
|
|
||||||
virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker);
|
|
||||||
virtual void releaseInputController(controller::InputController* input);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void keyPressEvent(const KeyEvent& event);
|
void keyPressEvent(const KeyEvent& event);
|
||||||
void keyReleaseEvent(const KeyEvent& event);
|
void keyReleaseEvent(const KeyEvent& event);
|
||||||
|
@ -135,8 +97,6 @@ private:
|
||||||
bool _captureEntityClicks;
|
bool _captureEntityClicks;
|
||||||
|
|
||||||
using InputKey = controller::InputController::Key;
|
using InputKey = controller::InputController::Key;
|
||||||
using InputControllerMap = std::map<InputKey, controller::InputController::Pointer>;
|
|
||||||
InputControllerMap _inputControllers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip
|
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <QtScript/QScriptContext>
|
#include <QtScript/QScriptContext>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <avatar/AvatarManager.h>
|
#include <avatar/AvatarManager.h>
|
||||||
#include <display-plugins/DisplayPlugin.h>
|
#include <display-plugins/DisplayPlugin.h>
|
||||||
#include <display-plugins/CompositorHelper.h>
|
#include <display-plugins/CompositorHelper.h>
|
||||||
|
@ -152,22 +153,31 @@ QString HMDScriptingInterface::preferredAudioOutput() const {
|
||||||
return qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice();
|
return qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const {
|
bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
bool result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "setHandLasers", Q_RETURN_ARG(bool, result),
|
||||||
|
Q_ARG(int, hands), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
offscreenUi->executeOnUiThread([offscreenUi, enabled] {
|
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
||||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
|
||||||
});
|
|
||||||
return qApp->getActiveDisplayPlugin()->setHandLaser(hands,
|
return qApp->getActiveDisplayPlugin()->setHandLaser(hands,
|
||||||
enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None,
|
enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None,
|
||||||
color, direction);
|
color, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) const {
|
bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
if (QThread::currentThread() != thread()) {
|
||||||
offscreenUi->executeOnUiThread([offscreenUi, enabled] {
|
bool result;
|
||||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
BLOCKING_INVOKE_METHOD(this, "setExtraLaser", Q_RETURN_ARG(bool, result),
|
||||||
});
|
Q_ARG(glm::vec3, worldStart), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
auto sensorToWorld = myAvatar->getSensorToWorldMatrix();
|
auto sensorToWorld = myAvatar->getSensorToWorldMatrix();
|
||||||
|
@ -179,11 +189,11 @@ bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enab
|
||||||
color, sensorStart, sensorDirection);
|
color, sensorStart, sensorDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HMDScriptingInterface::disableExtraLaser() const {
|
void HMDScriptingInterface::disableExtraLaser() {
|
||||||
setExtraLaser(vec3(0), false, vec4(0), vec3(0));
|
setExtraLaser(vec3(0), false, vec4(0), vec3(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HMDScriptingInterface::disableHandLasers(int hands) const {
|
void HMDScriptingInterface::disableHandLasers(int hands) {
|
||||||
setHandLasers(hands, false, vec4(0), vec3(0));
|
setHandLasers(hands, false, vec4(0), vec3(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,11 @@ public:
|
||||||
Q_INVOKABLE void requestHideHandControllers();
|
Q_INVOKABLE void requestHideHandControllers();
|
||||||
Q_INVOKABLE bool shouldShowHandControllers() const;
|
Q_INVOKABLE bool shouldShowHandControllers() const;
|
||||||
|
|
||||||
Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const;
|
Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction);
|
||||||
Q_INVOKABLE void disableHandLasers(int hands) const;
|
Q_INVOKABLE void disableHandLasers(int hands);
|
||||||
|
|
||||||
Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) const;
|
Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction);
|
||||||
Q_INVOKABLE void disableExtraLaser() const;
|
Q_INVOKABLE void disableExtraLaser();
|
||||||
|
|
||||||
|
|
||||||
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <MenuItemProperties.h>
|
#include <MenuItemProperties.h>
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ bool MenuScriptingInterface::menuExists(const QString& menu) {
|
||||||
return Menu::getInstance()->menuExists(menu);
|
return Menu::getInstance()->menuExists(menu);
|
||||||
}
|
}
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(Menu::getInstance(), "menuExists", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuExists",
|
||||||
Q_RETURN_ARG(bool, result),
|
Q_RETURN_ARG(bool, result),
|
||||||
Q_ARG(const QString&, menu));
|
Q_ARG(const QString&, menu));
|
||||||
return result;
|
return result;
|
||||||
|
@ -86,7 +87,7 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString&
|
||||||
return Menu::getInstance()->menuItemExists(menu, menuitem);
|
return Menu::getInstance()->menuItemExists(menu, menuitem);
|
||||||
}
|
}
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(Menu::getInstance(), "menuItemExists", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuItemExists",
|
||||||
Q_RETURN_ARG(bool, result),
|
Q_RETURN_ARG(bool, result),
|
||||||
Q_ARG(const QString&, menu),
|
Q_ARG(const QString&, menu),
|
||||||
Q_ARG(const QString&, menuitem));
|
Q_ARG(const QString&, menuitem));
|
||||||
|
@ -114,7 +115,7 @@ bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) {
|
||||||
return Menu::getInstance()->isOptionChecked(menuOption);
|
return Menu::getInstance()->isOptionChecked(menuOption);
|
||||||
}
|
}
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(Menu::getInstance(), "isOptionChecked", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isOptionChecked",
|
||||||
Q_RETURN_ARG(bool, result),
|
Q_RETURN_ARG(bool, result),
|
||||||
Q_ARG(const QString&, menuOption));
|
Q_ARG(const QString&, menuOption));
|
||||||
return result;
|
return result;
|
||||||
|
@ -131,7 +132,7 @@ bool MenuScriptingInterface::isMenuEnabled(const QString& menuOption) {
|
||||||
return Menu::getInstance()->isOptionChecked(menuOption);
|
return Menu::getInstance()->isOptionChecked(menuOption);
|
||||||
}
|
}
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(Menu::getInstance(), "isMenuEnabled", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isMenuEnabled",
|
||||||
Q_RETURN_ARG(bool, result),
|
Q_RETURN_ARG(bool, result),
|
||||||
Q_ARG(const QString&, menuOption));
|
Q_ARG(const QString&, menuOption));
|
||||||
return result;
|
return result;
|
||||||
|
@ -157,7 +158,7 @@ bool MenuScriptingInterface::isInfoViewVisible(const QString& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(Menu::getInstance(), "isInfoViewVisible", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isInfoViewVisible",
|
||||||
Q_RETURN_ARG(bool, result), Q_ARG(const QString&, path));
|
Q_RETURN_ARG(bool, result), Q_ARG(const QString&, path));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <QtCore/QLoggingCategory>
|
#include <QtCore/QLoggingCategory>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <Trace.h>
|
#include <Trace.h>
|
||||||
#include <StatTracker.h>
|
#include <StatTracker.h>
|
||||||
|
@ -57,20 +58,25 @@ void TestScriptingInterface::waitIdle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestScriptingInterface::loadTestScene(QString scene) {
|
bool TestScriptingInterface::loadTestScene(QString scene) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
bool result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "loadTestScene", Q_RETURN_ARG(bool, result), Q_ARG(QString, scene));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static const QString TEST_ROOT = "https://raw.githubusercontent.com/highfidelity/hifi_tests/master/";
|
static const QString TEST_ROOT = "https://raw.githubusercontent.com/highfidelity/hifi_tests/master/";
|
||||||
static const QString TEST_BINARY_ROOT = "https://hifi-public.s3.amazonaws.com/test_scene_data/";
|
static const QString TEST_BINARY_ROOT = "https://hifi-public.s3.amazonaws.com/test_scene_data/";
|
||||||
static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/";
|
static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/";
|
||||||
static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/";
|
static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/";
|
||||||
return DependencyManager::get<OffscreenUi>()->returnFromUiThread([scene]()->QVariant {
|
|
||||||
DependencyManager::get<ResourceManager>()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/");
|
DependencyManager::get<ResourceManager>()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/");
|
||||||
auto tree = qApp->getEntities()->getTree();
|
auto tree = qApp->getEntities()->getTree();
|
||||||
auto treeIsClient = tree->getIsClient();
|
auto treeIsClient = tree->getIsClient();
|
||||||
// Force the tree to accept the load regardless of permissions
|
// Force the tree to accept the load regardless of permissions
|
||||||
tree->setIsClient(false);
|
tree->setIsClient(false);
|
||||||
auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json");
|
auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json");
|
||||||
tree->setIsClient(treeIsClient);
|
tree->setIsClient(treeIsClient);
|
||||||
return result;
|
return result;
|
||||||
}).toBool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestScriptingInterface::startTracing(QString logrules) {
|
bool TestScriptingInterface::startTracing(QString logrules) {
|
||||||
|
|
|
@ -9,11 +9,14 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "WindowScriptingInterface.h"
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QScriptValue>
|
#include <QScriptValue>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
|
|
||||||
#include <display-plugins/CompositorHelper.h>
|
#include <display-plugins/CompositorHelper.h>
|
||||||
|
@ -24,8 +27,6 @@
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "OffscreenUi.h"
|
#include "OffscreenUi.h"
|
||||||
|
|
||||||
#include "WindowScriptingInterface.h"
|
|
||||||
|
|
||||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
|
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
|
||||||
static const QString LAST_BROWSE_ASSETS_LOCATION_SETTING = "LastBrowseAssetsLocation";
|
static const QString LAST_BROWSE_ASSETS_LOCATION_SETTING = "LastBrowseAssetsLocation";
|
||||||
|
@ -316,7 +317,7 @@ bool WindowScriptingInterface::isPhysicsEnabled() {
|
||||||
int WindowScriptingInterface::openMessageBox(QString title, QString text, int buttons, int defaultButton) {
|
int WindowScriptingInterface::openMessageBox(QString title, QString text, int buttons, int defaultButton) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
int result;
|
int result;
|
||||||
QMetaObject::invokeMethod(this, "openMessageBox", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "openMessageBox",
|
||||||
Q_RETURN_ARG(int, result),
|
Q_RETURN_ARG(int, result),
|
||||||
Q_ARG(QString, title),
|
Q_ARG(QString, title),
|
||||||
Q_ARG(QString, text),
|
Q_ARG(QString, text),
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <QtScript/QScriptValue>
|
#include <QtScript/QScriptValue>
|
||||||
#include <QtWidgets/QMessageBox>
|
#include <QtWidgets/QMessageBox>
|
||||||
|
|
||||||
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
class CustomPromptResult {
|
class CustomPromptResult {
|
||||||
public:
|
public:
|
||||||
QVariant value;
|
QVariant value;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <ScriptEngines.h>
|
#include <ScriptEngines.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
|
||||||
|
@ -115,7 +116,7 @@ void JSConsole::executeCommand(const QString& command) {
|
||||||
|
|
||||||
QScriptValue JSConsole::executeCommandInWatcher(const QString& command) {
|
QScriptValue JSConsole::executeCommandInWatcher(const QString& command) {
|
||||||
QScriptValue result;
|
QScriptValue result;
|
||||||
QMetaObject::invokeMethod(_scriptEngine, "evaluate", Qt::ConnectionType::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(_scriptEngine, "evaluate",
|
||||||
Q_RETURN_ARG(QScriptValue, result),
|
Q_RETURN_ARG(QScriptValue, result),
|
||||||
Q_ARG(const QString&, command),
|
Q_ARG(const QString&, command),
|
||||||
Q_ARG(const QString&, _consoleFileName));
|
Q_ARG(const QString&, _consoleFileName));
|
||||||
|
|
|
@ -45,11 +45,13 @@ Image3DOverlay::~Image3DOverlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image3DOverlay::update(float deltatime) {
|
void Image3DOverlay::update(float deltatime) {
|
||||||
|
#if OVERLAY_PANELS
|
||||||
if (usecTimestampNow() > _transformExpiry) {
|
if (usecTimestampNow() > _transformExpiry) {
|
||||||
Transform transform = getTransform();
|
Transform transform = getTransform();
|
||||||
applyTransformTo(transform);
|
applyTransformTo(transform);
|
||||||
setTransform(transform);
|
setTransform(transform);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image3DOverlay::render(RenderArgs* args) {
|
void Image3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
|
@ -84,9 +84,9 @@ public:
|
||||||
void setColorPulse(float value) { _colorPulse = value; }
|
void setColorPulse(float value) { _colorPulse = value; }
|
||||||
void setAlphaPulse(float value) { _alphaPulse = value; }
|
void setAlphaPulse(float value) { _alphaPulse = value; }
|
||||||
|
|
||||||
virtual void setProperties(const QVariantMap& properties);
|
Q_INVOKABLE virtual void setProperties(const QVariantMap& properties);
|
||||||
virtual Overlay* createClone() const = 0;
|
Q_INVOKABLE virtual Overlay* createClone() const = 0;
|
||||||
virtual QVariant getProperty(const QString& property);
|
Q_INVOKABLE virtual QVariant getProperty(const QString& property);
|
||||||
|
|
||||||
render::ItemID getRenderItemID() const { return _renderItemID; }
|
render::ItemID getRenderItemID() const { return _renderItemID; }
|
||||||
void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; }
|
void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; }
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "OverlayPanel.h"
|
#include "OverlayPanel.h"
|
||||||
|
|
||||||
|
#if OVERLAY_PANELS
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
@ -185,3 +187,4 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) {
|
||||||
pointTransformAtCamera(transform, getOffsetRotation());
|
pointTransformAtCamera(transform, getOffsetRotation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -22,6 +22,7 @@
|
||||||
#include "Billboardable.h"
|
#include "Billboardable.h"
|
||||||
#include "Overlay.h"
|
#include "Overlay.h"
|
||||||
|
|
||||||
|
#if OVERLAY_PANELS
|
||||||
class PropertyBinding {
|
class PropertyBinding {
|
||||||
public:
|
public:
|
||||||
PropertyBinding() {}
|
PropertyBinding() {}
|
||||||
|
@ -80,4 +81,6 @@ private:
|
||||||
QScriptEngine* _scriptEngine;
|
QScriptEngine* _scriptEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // hifi_OverlayPanel_h
|
#endif // hifi_OverlayPanel_h
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <QtScript/QScriptValueIterator>
|
#include <QtScript/QScriptValueIterator>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <OffscreenUi.h>
|
#include <OffscreenUi.h>
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
@ -39,34 +40,39 @@
|
||||||
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
||||||
|
|
||||||
void Overlays::cleanupAllOverlays() {
|
void Overlays::cleanupAllOverlays() {
|
||||||
|
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
||||||
|
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&_lock);
|
QMutexLocker locker(&_mutex);
|
||||||
QWriteLocker deleteLock(&_deleteLock);
|
overlaysHUD.swap(_overlaysHUD);
|
||||||
foreach(Overlay::Pointer overlay, _overlaysHUD) {
|
overlaysWorld.swap(_overlaysWorld);
|
||||||
_overlaysToDelete.push_back(overlay);
|
|
||||||
}
|
|
||||||
foreach(Overlay::Pointer overlay, _overlaysWorld) {
|
|
||||||
_overlaysToDelete.push_back(overlay);
|
|
||||||
}
|
|
||||||
_overlaysHUD.clear();
|
|
||||||
_overlaysWorld.clear();
|
|
||||||
_panels.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(Overlay::Pointer overlay, overlaysHUD) {
|
||||||
|
_overlaysToDelete.push_back(overlay);
|
||||||
|
}
|
||||||
|
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
||||||
|
_overlaysToDelete.push_back(overlay);
|
||||||
|
}
|
||||||
|
#if OVERLAY_PANELS
|
||||||
|
_panels.clear();
|
||||||
|
#endif
|
||||||
cleanupOverlaysToDelete();
|
cleanupOverlaysToDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::init() {
|
void Overlays::init() {
|
||||||
|
#if OVERLAY_PANELS
|
||||||
_scriptEngine = new QScriptEngine();
|
_scriptEngine = new QScriptEngine();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::update(float deltatime) {
|
void Overlays::update(float deltatime) {
|
||||||
|
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&_lock);
|
QMutexLocker locker(&_mutex);
|
||||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
foreach(const auto& thisOverlay, _overlaysHUD) {
|
||||||
thisOverlay->update(deltatime);
|
thisOverlay->update(deltatime);
|
||||||
}
|
}
|
||||||
foreach(Overlay::Pointer thisOverlay, _overlaysWorld) {
|
foreach(const auto& thisOverlay, _overlaysWorld) {
|
||||||
thisOverlay->update(deltatime);
|
thisOverlay->update(deltatime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,8 +86,6 @@ void Overlays::cleanupOverlaysToDelete() {
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
|
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&_deleteLock);
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Overlay::Pointer overlay = _overlaysToDelete.takeLast();
|
Overlay::Pointer overlay = _overlaysToDelete.takeLast();
|
||||||
|
|
||||||
|
@ -100,7 +104,6 @@ void Overlays::cleanupOverlaysToDelete() {
|
||||||
|
|
||||||
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||||
PROFILE_RANGE(render_overlays, __FUNCTION__);
|
PROFILE_RANGE(render_overlays, __FUNCTION__);
|
||||||
QReadLocker lock(&_lock);
|
|
||||||
gpu::Batch& batch = *renderArgs->_batch;
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
@ -111,7 +114,7 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||||
int height = size.y;
|
int height = size.y;
|
||||||
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
|
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
|
||||||
|
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
||||||
|
|
||||||
// Reset all batch pipeline settings between overlay
|
// Reset all batch pipeline settings between overlay
|
||||||
|
@ -126,16 +129,17 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::disable() {
|
void Overlays::disable() {
|
||||||
QWriteLocker lock(&_lock);
|
|
||||||
_enabled = false;
|
_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::enable() {
|
void Overlays::enable() {
|
||||||
QWriteLocker lock(&_lock);
|
|
||||||
_enabled = true;
|
_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note, can't be invoked by scripts, but can be called by the InterfaceParentFinder
|
||||||
|
// class on packet processing threads
|
||||||
Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
|
Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
if (_overlaysHUD.contains(id)) {
|
if (_overlaysHUD.contains(id)) {
|
||||||
return _overlaysHUD[id];
|
return _overlaysHUD[id];
|
||||||
}
|
}
|
||||||
|
@ -146,6 +150,12 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) {
|
OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
OverlayID result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "addOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(QString, type), Q_ARG(QVariant, properties));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer thisOverlay = nullptr;
|
Overlay::Pointer thisOverlay = nullptr;
|
||||||
|
|
||||||
if (type == ImageOverlay::TYPE) {
|
if (type == ImageOverlay::TYPE) {
|
||||||
|
@ -185,19 +195,22 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties)
|
||||||
return UNKNOWN_OVERLAY_ID;
|
return UNKNOWN_OVERLAY_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayID Overlays::addOverlay(Overlay::Pointer overlay) {
|
OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
||||||
QWriteLocker lock(&_lock);
|
|
||||||
OverlayID thisID = OverlayID(QUuid::createUuid());
|
OverlayID thisID = OverlayID(QUuid::createUuid());
|
||||||
overlay->setOverlayID(thisID);
|
overlay->setOverlayID(thisID);
|
||||||
overlay->setStackOrder(_stackOrder++);
|
overlay->setStackOrder(_stackOrder++);
|
||||||
if (overlay->is3D()) {
|
if (overlay->is3D()) {
|
||||||
_overlaysWorld[thisID] = overlay;
|
{
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
|
_overlaysWorld[thisID] = overlay;
|
||||||
|
}
|
||||||
|
|
||||||
render::ScenePointer scene = qApp->getMain3DScene();
|
render::ScenePointer scene = qApp->getMain3DScene();
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
overlay->addToScene(overlay, scene, transaction);
|
overlay->addToScene(overlay, scene, transaction);
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
} else {
|
} else {
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
_overlaysHUD[thisID] = overlay;
|
_overlaysHUD[thisID] = overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,14 +218,22 @@ OverlayID Overlays::addOverlay(Overlay::Pointer overlay) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayID Overlays::cloneOverlay(OverlayID id) {
|
OverlayID Overlays::cloneOverlay(OverlayID id) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
OverlayID result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "cloneOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(OverlayID, id));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||||
|
|
||||||
if (thisOverlay) {
|
if (thisOverlay) {
|
||||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone()));
|
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone()));
|
||||||
|
#if OVERLAY_PANELS
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
||||||
if (attachable && attachable->getParentPanel()) {
|
if (attachable && attachable->getParentPanel()) {
|
||||||
attachable->getParentPanel()->addChild(cloneId);
|
attachable->getParentPanel()->addChild(cloneId);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return cloneId;
|
return cloneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,21 +241,32 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
|
bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
|
||||||
QWriteLocker lock(&_lock);
|
if (QThread::currentThread() != thread()) {
|
||||||
|
// NOTE editOverlay can be called very frequently in scripts and can't afford to
|
||||||
|
// block waiting on the main thread. Additionally, no script actually
|
||||||
|
// examines the return value and does something useful with it, so use a non-blocking
|
||||||
|
// invoke and just always return true
|
||||||
|
QMetaObject::invokeMethod(this, "editOverlay", Q_ARG(OverlayID, id), Q_ARG(QVariant, properties));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||||
if (thisOverlay) {
|
if (thisOverlay) {
|
||||||
thisOverlay->setProperties(properties.toMap());
|
thisOverlay->setProperties(properties.toMap());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Overlays::editOverlays(const QVariant& propertiesById) {
|
bool Overlays::editOverlays(const QVariant& propertiesById) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
// NOTE see comment on editOverlay for why this is not a blocking call
|
||||||
|
QMetaObject::invokeMethod(this, "editOverlays", Q_ARG(QVariant, propertiesById));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap map = propertiesById.toMap();
|
QVariantMap map = propertiesById.toMap();
|
||||||
bool success = true;
|
bool success = true;
|
||||||
QWriteLocker lock(&_lock);
|
|
||||||
for (const auto& key : map.keys()) {
|
for (const auto& key : map.keys()) {
|
||||||
OverlayID id = OverlayID(key);
|
OverlayID id = OverlayID(key);
|
||||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||||
|
@ -249,10 +281,15 @@ bool Overlays::editOverlays(const QVariant& propertiesById) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::deleteOverlay(OverlayID id) {
|
void Overlays::deleteOverlay(OverlayID id) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "deleteOverlay", Q_ARG(OverlayID, id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer overlayToDelete;
|
Overlay::Pointer overlayToDelete;
|
||||||
|
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&_lock);
|
QMutexLocker locker(&_mutex);
|
||||||
if (_overlaysHUD.contains(id)) {
|
if (_overlaysHUD.contains(id)) {
|
||||||
overlayToDelete = _overlaysHUD.take(id);
|
overlayToDelete = _overlaysHUD.take(id);
|
||||||
} else if (_overlaysWorld.contains(id)) {
|
} else if (_overlaysWorld.contains(id)) {
|
||||||
|
@ -262,19 +299,25 @@ void Overlays::deleteOverlay(OverlayID id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OVERLAY_PANELS
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlayToDelete);
|
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlayToDelete);
|
||||||
if (attachable && attachable->getParentPanel()) {
|
if (attachable && attachable->getParentPanel()) {
|
||||||
attachable->getParentPanel()->removeChild(id);
|
attachable->getParentPanel()->removeChild(id);
|
||||||
attachable->setParentPanel(nullptr);
|
attachable->setParentPanel(nullptr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QWriteLocker lock(&_deleteLock);
|
|
||||||
_overlaysToDelete.push_back(overlayToDelete);
|
_overlaysToDelete.push_back(overlayToDelete);
|
||||||
|
|
||||||
emit overlayDeleted(id);
|
emit overlayDeleted(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Overlays::getOverlayType(OverlayID overlayId) const {
|
QString Overlays::getOverlayType(OverlayID overlayId) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QString result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(OverlayID, overlayId));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer overlay = getOverlay(overlayId);
|
Overlay::Pointer overlay = getOverlay(overlayId);
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
return overlay->getType();
|
return overlay->getType();
|
||||||
|
@ -283,6 +326,12 @@ QString Overlays::getOverlayType(OverlayID overlayId) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* Overlays::getOverlayObject(OverlayID id) {
|
QObject* Overlays::getOverlayObject(OverlayID id) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QObject* result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||||
if (thisOverlay) {
|
if (thisOverlay) {
|
||||||
return qobject_cast<QObject*>(&(*thisOverlay));
|
return qobject_cast<QObject*>(&(*thisOverlay));
|
||||||
|
@ -290,6 +339,7 @@ QObject* Overlays::getOverlayObject(OverlayID id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OVERLAY_PANELS
|
||||||
OverlayID Overlays::getParentPanel(OverlayID childId) const {
|
OverlayID Overlays::getParentPanel(OverlayID childId) const {
|
||||||
Overlay::Pointer overlay = getOverlay(childId);
|
Overlay::Pointer overlay = getOverlay(childId);
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
|
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
|
||||||
|
@ -330,33 +380,31 @@ void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||||
glm::vec2 pointCopy = point;
|
if (QThread::currentThread() != thread()) {
|
||||||
QReadLocker lock(&_lock);
|
OverlayID result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "getOverlayAtPoint", Q_RETURN_ARG(OverlayID, result), Q_ARG(glm::vec2, point));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_enabled) {
|
if (!_enabled) {
|
||||||
return UNKNOWN_OVERLAY_ID;
|
return UNKNOWN_OVERLAY_ID;
|
||||||
}
|
}
|
||||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysHUD);
|
|
||||||
|
|
||||||
const float LARGE_NEGATIVE_FLOAT = -9999999;
|
QMutexLocker locker(&_mutex);
|
||||||
glm::vec3 origin(pointCopy.x, pointCopy.y, LARGE_NEGATIVE_FLOAT);
|
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysHUD);
|
||||||
glm::vec3 direction(0, 0, 1);
|
|
||||||
glm::vec3 thisSurfaceNormal;
|
|
||||||
unsigned int bestStackOrder = 0;
|
unsigned int bestStackOrder = 0;
|
||||||
OverlayID bestOverlayID = UNKNOWN_OVERLAY_ID;
|
OverlayID bestOverlayID = UNKNOWN_OVERLAY_ID;
|
||||||
|
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
OverlayID thisID = i.key();
|
auto thisOverlay = std::dynamic_pointer_cast<Overlay2D>(i.value());
|
||||||
if (!i.value()->is3D()) {
|
if (thisOverlay && thisOverlay->getVisible() && thisOverlay->isLoaded() &&
|
||||||
auto thisOverlay = std::dynamic_pointer_cast<Overlay2D>(i.value());
|
thisOverlay->getBoundingRect().contains(point.x, point.y, false)) {
|
||||||
if (thisOverlay && thisOverlay->getVisible() && thisOverlay->isLoaded() &&
|
if (thisOverlay->getStackOrder() > bestStackOrder) {
|
||||||
thisOverlay->getBoundingRect().contains(pointCopy.x, pointCopy.y, false)) {
|
bestOverlayID = i.key();
|
||||||
if (thisOverlay->getStackOrder() > bestStackOrder) {
|
bestStackOrder = thisOverlay->getStackOrder();
|
||||||
bestOverlayID = thisID;
|
|
||||||
bestStackOrder = thisOverlay->getStackOrder();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,9 +413,14 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) {
|
OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
OverlayPropertyResult result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "getProperty", Q_RETURN_ARG(OverlayPropertyResult, result), Q_ARG(OverlayID, id), Q_ARG(QString, property));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
OverlayPropertyResult result;
|
OverlayPropertyResult result;
|
||||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||||
QReadLocker lock(&_lock);
|
|
||||||
if (thisOverlay && thisOverlay->supportsGetProperty()) {
|
if (thisOverlay && thisOverlay->supportsGetProperty()) {
|
||||||
result.value = thisOverlay->getProperty(property);
|
result.value = thisOverlay->getProperty(property);
|
||||||
}
|
}
|
||||||
|
@ -405,10 +458,22 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR
|
||||||
const QVector<OverlayID>& overlaysToInclude,
|
const QVector<OverlayID>& overlaysToInclude,
|
||||||
const QVector<OverlayID>& overlaysToDiscard,
|
const QVector<OverlayID>& overlaysToDiscard,
|
||||||
bool visibleOnly, bool collidableOnly) {
|
bool visibleOnly, bool collidableOnly) {
|
||||||
QReadLocker lock(&_lock);
|
if (QThread::currentThread() != thread()) {
|
||||||
|
RayToOverlayIntersectionResult result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "findRayIntersectionInternal", Q_RETURN_ARG(RayToOverlayIntersectionResult, result),
|
||||||
|
Q_ARG(PickRay, ray),
|
||||||
|
Q_ARG(bool, precisionPicking),
|
||||||
|
Q_ARG(QVector<OverlayID>, overlaysToInclude),
|
||||||
|
Q_ARG(QVector<OverlayID>, overlaysToDiscard),
|
||||||
|
Q_ARG(bool, visibleOnly),
|
||||||
|
Q_ARG(bool, collidableOnly));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
float bestDistance = std::numeric_limits<float>::max();
|
float bestDistance = std::numeric_limits<float>::max();
|
||||||
bool bestIsFront = false;
|
bool bestIsFront = false;
|
||||||
|
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
RayToOverlayIntersectionResult result;
|
RayToOverlayIntersectionResult result;
|
||||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
|
@ -448,16 +513,6 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() :
|
|
||||||
intersects(false),
|
|
||||||
overlayID(UNKNOWN_OVERLAY_ID),
|
|
||||||
distance(0),
|
|
||||||
face(),
|
|
||||||
intersection(),
|
|
||||||
extraInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) {
|
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) {
|
||||||
auto obj = engine->newObject();
|
auto obj = engine->newObject();
|
||||||
obj.setProperty("intersects", value.intersects);
|
obj.setProperty("intersects", value.intersects);
|
||||||
|
@ -531,7 +586,12 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Overlays::isLoaded(OverlayID id) {
|
bool Overlays::isLoaded(OverlayID id) {
|
||||||
QReadLocker lock(&_lock);
|
if (QThread::currentThread() != thread()) {
|
||||||
|
bool result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||||
if (!thisOverlay) {
|
if (!thisOverlay) {
|
||||||
return false; // not found
|
return false; // not found
|
||||||
|
@ -539,14 +599,27 @@ bool Overlays::isLoaded(OverlayID id) {
|
||||||
return thisOverlay->isLoaded();
|
return thisOverlay->isLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF Overlays::textSize(OverlayID id, const QString& text) const {
|
QSizeF Overlays::textSize(OverlayID id, const QString& text) {
|
||||||
Overlay::Pointer thisOverlay = _overlaysHUD[id];
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QSizeF result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(OverlayID, id), Q_ARG(QString, text));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlay::Pointer thisOverlay;
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
|
thisOverlay = _overlaysHUD[id];
|
||||||
|
}
|
||||||
if (thisOverlay) {
|
if (thisOverlay) {
|
||||||
if (auto textOverlay = std::dynamic_pointer_cast<TextOverlay>(thisOverlay)) {
|
if (auto textOverlay = std::dynamic_pointer_cast<TextOverlay>(thisOverlay)) {
|
||||||
return textOverlay->textSize(text);
|
return textOverlay->textSize(text);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
thisOverlay = _overlaysWorld[id];
|
{
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
|
thisOverlay = _overlaysWorld[id];
|
||||||
|
}
|
||||||
if (auto text3dOverlay = std::dynamic_pointer_cast<Text3DOverlay>(thisOverlay)) {
|
if (auto text3dOverlay = std::dynamic_pointer_cast<Text3DOverlay>(thisOverlay)) {
|
||||||
return text3dOverlay->textSize(text);
|
return text3dOverlay->textSize(text);
|
||||||
}
|
}
|
||||||
|
@ -554,6 +627,7 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) const {
|
||||||
return QSizeF(0.0f, 0.0f);
|
return QSizeF(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OVERLAY_PANELS
|
||||||
OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) {
|
OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) {
|
||||||
QWriteLocker lock(&_lock);
|
QWriteLocker lock(&_lock);
|
||||||
|
|
||||||
|
@ -607,8 +681,16 @@ void Overlays::deletePanel(OverlayID panelId) {
|
||||||
|
|
||||||
emit panelDeleted(panelId);
|
emit panelDeleted(panelId);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Overlays::isAddedOverlay(OverlayID id) {
|
bool Overlays::isAddedOverlay(OverlayID id) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
bool result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "isAddedOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
|
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,20 +718,43 @@ void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) {
|
||||||
emit hoverLeaveOverlay(id, event);
|
emit hoverLeaveOverlay(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayID Overlays::getKeyboardFocusOverlay() const {
|
OverlayID Overlays::getKeyboardFocusOverlay() {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
OverlayID result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "getKeyboardFocusOverlay", Q_RETURN_ARG(OverlayID, result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return qApp->getKeyboardFocusOverlay();
|
return qApp->getKeyboardFocusOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::setKeyboardFocusOverlay(OverlayID id) {
|
void Overlays::setKeyboardFocusOverlay(OverlayID id) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "setKeyboardFocusOverlay", Q_ARG(OverlayID, id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qApp->setKeyboardFocusOverlay(id);
|
qApp->setKeyboardFocusOverlay(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Overlays::width() const {
|
float Overlays::width() {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
float result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "width", Q_RETURN_ARG(float, result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
return offscreenUi->getWindow()->size().width();
|
return offscreenUi->getWindow()->size().width();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Overlays::height() const {
|
float Overlays::height() {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
float result;
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "height", Q_RETURN_ARG(float, result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
return offscreenUi->getWindow()->size().height();
|
return offscreenUi->getWindow()->size().height();
|
||||||
}
|
}
|
||||||
|
@ -705,7 +810,6 @@ PointerEvent Overlays::calculatePointerEvent(Overlay::Pointer overlay, PickRay r
|
||||||
|
|
||||||
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlay);
|
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlay);
|
||||||
|
|
||||||
QReadLocker lock(&_lock);
|
|
||||||
auto position = thisOverlay->getPosition();
|
auto position = thisOverlay->getPosition();
|
||||||
auto rotation = thisOverlay->getRotation();
|
auto rotation = thisOverlay->getRotation();
|
||||||
auto dimensions = thisOverlay->getSize();
|
auto dimensions = thisOverlay->getSize();
|
||||||
|
@ -854,9 +958,14 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) const {
|
QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) {
|
||||||
QVector<QUuid> result;
|
QVector<QUuid> result;
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
BLOCKING_INVOKE_METHOD(this, "findOverlays", Q_RETURN_ARG(QVector<QUuid>, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
||||||
int checked = 0;
|
int checked = 0;
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
|
|
|
@ -25,8 +25,9 @@
|
||||||
#include <PointerEvent.h>
|
#include <PointerEvent.h>
|
||||||
|
|
||||||
#include "Overlay.h"
|
#include "Overlay.h"
|
||||||
#include "OverlayPanel.h"
|
|
||||||
#include "PanelAttachable.h"
|
#include "PanelAttachable.h"
|
||||||
|
#include "OverlayPanel.h"
|
||||||
|
|
||||||
class PickRay;
|
class PickRay;
|
||||||
|
|
||||||
|
@ -41,6 +42,8 @@ Q_DECLARE_METATYPE(OverlayPropertyResult);
|
||||||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value);
|
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value);
|
||||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value);
|
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value);
|
||||||
|
|
||||||
|
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @typedef Overlays.RayToOverlayIntersectionResult
|
* @typedef Overlays.RayToOverlayIntersectionResult
|
||||||
* @property {bool} intersects True if the PickRay intersected with a 3D overlay.
|
* @property {bool} intersects True if the PickRay intersected with a 3D overlay.
|
||||||
|
@ -51,10 +54,9 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPro
|
||||||
*/
|
*/
|
||||||
class RayToOverlayIntersectionResult {
|
class RayToOverlayIntersectionResult {
|
||||||
public:
|
public:
|
||||||
RayToOverlayIntersectionResult();
|
bool intersects { false };
|
||||||
bool intersects;
|
OverlayID overlayID { UNKNOWN_OVERLAY_ID };
|
||||||
OverlayID overlayID;
|
float distance { 0 };
|
||||||
float distance;
|
|
||||||
BoxFace face;
|
BoxFace face;
|
||||||
glm::vec3 surfaceNormal;
|
glm::vec3 surfaceNormal;
|
||||||
glm::vec3 intersection;
|
glm::vec3 intersection;
|
||||||
|
@ -77,8 +79,6 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
||||||
* @namespace Overlays
|
* @namespace Overlays
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
|
||||||
|
|
||||||
class Overlays : public QObject {
|
class Overlays : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -94,11 +94,13 @@ public:
|
||||||
void enable();
|
void enable();
|
||||||
|
|
||||||
Overlay::Pointer getOverlay(OverlayID id) const;
|
Overlay::Pointer getOverlay(OverlayID id) const;
|
||||||
|
#if OVERLAY_PANELS
|
||||||
OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; }
|
OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; }
|
||||||
|
#endif
|
||||||
|
|
||||||
/// adds an overlay that's already been created
|
/// adds an overlay that's already been created
|
||||||
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
||||||
OverlayID addOverlay(Overlay::Pointer overlay);
|
OverlayID addOverlay(const Overlay::Pointer& overlay);
|
||||||
|
|
||||||
bool mousePressEvent(QMouseEvent* event);
|
bool mousePressEvent(QMouseEvent* event);
|
||||||
bool mouseDoublePressEvent(QMouseEvent* event);
|
bool mouseDoublePressEvent(QMouseEvent* event);
|
||||||
|
@ -156,7 +158,7 @@ public slots:
|
||||||
* @param {Overlays.OverlayID} overlayID The ID of the overlay to get the type of.
|
* @param {Overlays.OverlayID} overlayID The ID of the overlay to get the type of.
|
||||||
* @return {string} The type of the overlay if found, otherwise the empty string.
|
* @return {string} The type of the overlay if found, otherwise the empty string.
|
||||||
*/
|
*/
|
||||||
QString getOverlayType(OverlayID overlayId) const;
|
QString getOverlayType(OverlayID overlayId);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the overlay Script object.
|
* Get the overlay Script object.
|
||||||
|
@ -215,7 +217,7 @@ public slots:
|
||||||
* @param {float} radius search radius
|
* @param {float} radius search radius
|
||||||
* @return {Overlays.OverlayID[]} list of overlays withing the radius
|
* @return {Overlays.OverlayID[]} list of overlays withing the radius
|
||||||
*/
|
*/
|
||||||
QVector<QUuid> findOverlays(const glm::vec3& center, float radius) const;
|
QVector<QUuid> findOverlays(const glm::vec3& center, float radius);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Check whether an overlay's assets have been loaded. For example, if the
|
* Check whether an overlay's assets have been loaded. For example, if the
|
||||||
|
@ -237,7 +239,7 @@ public slots:
|
||||||
* @param {string} The string to measure.
|
* @param {string} The string to measure.
|
||||||
* @return {Vec2} The size of the text.
|
* @return {Vec2} The size of the text.
|
||||||
*/
|
*/
|
||||||
QSizeF textSize(OverlayID id, const QString& text) const;
|
QSizeF textSize(OverlayID id, const QString& text);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the width of the virtual 2D HUD.
|
* Get the width of the virtual 2D HUD.
|
||||||
|
@ -245,7 +247,7 @@ public slots:
|
||||||
* @function Overlays.width
|
* @function Overlays.width
|
||||||
* @return {float} The width of the 2D HUD.
|
* @return {float} The width of the 2D HUD.
|
||||||
*/
|
*/
|
||||||
float width() const;
|
float width();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the height of the virtual 2D HUD.
|
* Get the height of the virtual 2D HUD.
|
||||||
|
@ -253,11 +255,12 @@ public slots:
|
||||||
* @function Overlays.height
|
* @function Overlays.height
|
||||||
* @return {float} The height of the 2D HUD.
|
* @return {float} The height of the 2D HUD.
|
||||||
*/
|
*/
|
||||||
float height() const;
|
float height();
|
||||||
|
|
||||||
/// return true if there is an overlay with that id else false
|
/// return true if there is an overlay with that id else false
|
||||||
bool isAddedOverlay(OverlayID id);
|
bool isAddedOverlay(OverlayID id);
|
||||||
|
|
||||||
|
#if OVERLAY_PANELS
|
||||||
OverlayID getParentPanel(OverlayID childId) const;
|
OverlayID getParentPanel(OverlayID childId) const;
|
||||||
void setParentPanel(OverlayID childId, OverlayID panelId);
|
void setParentPanel(OverlayID childId, OverlayID panelId);
|
||||||
|
|
||||||
|
@ -279,6 +282,8 @@ public slots:
|
||||||
/// return true if there is a panel with that id else false
|
/// return true if there is a panel with that id else false
|
||||||
bool isAddedPanel(OverlayID id) { return _panels.contains(id); }
|
bool isAddedPanel(OverlayID id) { return _panels.contains(id); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
void sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||||
void sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
void sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||||
void sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
void sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||||
|
@ -287,7 +292,7 @@ public slots:
|
||||||
void sendHoverOverOverlay(OverlayID id, PointerEvent event);
|
void sendHoverOverOverlay(OverlayID id, PointerEvent event);
|
||||||
void sendHoverLeaveOverlay(OverlayID id, PointerEvent event);
|
void sendHoverLeaveOverlay(OverlayID id, PointerEvent event);
|
||||||
|
|
||||||
OverlayID getKeyboardFocusOverlay() const;
|
OverlayID getKeyboardFocusOverlay();
|
||||||
void setKeyboardFocusOverlay(OverlayID id);
|
void setKeyboardFocusOverlay(OverlayID id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -314,15 +319,18 @@ signals:
|
||||||
private:
|
private:
|
||||||
void cleanupOverlaysToDelete();
|
void cleanupOverlaysToDelete();
|
||||||
|
|
||||||
|
mutable QMutex _mutex;
|
||||||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||||
|
#if OVERLAY_PANELS
|
||||||
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
||||||
|
#endif
|
||||||
QList<Overlay::Pointer> _overlaysToDelete;
|
QList<Overlay::Pointer> _overlaysToDelete;
|
||||||
unsigned int _stackOrder { 1 };
|
unsigned int _stackOrder { 1 };
|
||||||
|
|
||||||
QReadWriteLock _lock;
|
#if OVERLAY_PANELS
|
||||||
QReadWriteLock _deleteLock;
|
|
||||||
QScriptEngine* _scriptEngine;
|
QScriptEngine* _scriptEngine;
|
||||||
|
#endif
|
||||||
bool _enabled = true;
|
bool _enabled = true;
|
||||||
|
|
||||||
PointerEvent calculatePointerEvent(Overlay::Pointer overlay, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
|
PointerEvent calculatePointerEvent(Overlay::Pointer overlay, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
|
||||||
|
@ -331,7 +339,7 @@ private:
|
||||||
OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID };
|
OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID };
|
||||||
OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID };
|
OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID };
|
||||||
|
|
||||||
RayToOverlayIntersectionResult findRayIntersectionInternal(const PickRay& ray, bool precisionPicking,
|
Q_INVOKABLE RayToOverlayIntersectionResult findRayIntersectionInternal(const PickRay& ray, bool precisionPicking,
|
||||||
const QVector<OverlayID>& overlaysToInclude,
|
const QVector<OverlayID>& overlaysToInclude,
|
||||||
const QVector<OverlayID>& overlaysToDiscard,
|
const QVector<OverlayID>& overlaysToDiscard,
|
||||||
bool visibleOnly = false, bool collidableOnly = false);
|
bool visibleOnly = false, bool collidableOnly = false);
|
||||||
|
|
|
@ -16,11 +16,15 @@
|
||||||
#include "OverlayPanel.h"
|
#include "OverlayPanel.h"
|
||||||
|
|
||||||
bool PanelAttachable::getParentVisible() const {
|
bool PanelAttachable::getParentVisible() const {
|
||||||
|
#if OVERLAY_PANELS
|
||||||
if (getParentPanel()) {
|
if (getParentPanel()) {
|
||||||
return getParentPanel()->getVisible() && getParentPanel()->getParentVisible();
|
return getParentPanel()->getVisible() && getParentPanel()->getParentVisible();
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant PanelAttachable::getProperty(const QString& property) {
|
QVariant PanelAttachable::getProperty(const QString& property) {
|
||||||
|
@ -61,11 +65,13 @@ void PanelAttachable::applyTransformTo(Transform& transform, bool force) {
|
||||||
if (force || usecTimestampNow() > _transformExpiry) {
|
if (force || usecTimestampNow() > _transformExpiry) {
|
||||||
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
||||||
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
||||||
|
#if OVERLAY_PANELS
|
||||||
if (getParentPanel()) {
|
if (getParentPanel()) {
|
||||||
getParentPanel()->applyTransformTo(transform, true);
|
getParentPanel()->applyTransformTo(transform, true);
|
||||||
transform.postTranslate(getOffsetPosition());
|
transform.postTranslate(getOffsetPosition());
|
||||||
transform.postRotate(getOffsetRotation());
|
transform.postRotate(getOffsetRotation());
|
||||||
transform.postScale(getOffsetScale());
|
transform.postScale(getOffsetScale());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#ifndef hifi_PanelAttachable_h
|
#ifndef hifi_PanelAttachable_h
|
||||||
#define hifi_PanelAttachable_h
|
#define hifi_PanelAttachable_h
|
||||||
|
|
||||||
|
#define OVERLAY_PANELS 0
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
@ -39,18 +41,21 @@
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
class OverlayPanel;
|
class OverlayPanel;
|
||||||
|
|
||||||
class PanelAttachable {
|
class PanelAttachable {
|
||||||
public:
|
public:
|
||||||
// getters
|
// getters
|
||||||
|
#if OVERLAY_PANELS
|
||||||
std::shared_ptr<OverlayPanel> getParentPanel() const { return _parentPanel; }
|
std::shared_ptr<OverlayPanel> getParentPanel() const { return _parentPanel; }
|
||||||
|
#endif
|
||||||
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
||||||
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
||||||
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
||||||
bool getParentVisible() const;
|
bool getParentVisible() const;
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
|
#if OVERLAY_PANELS
|
||||||
void setParentPanel(std::shared_ptr<OverlayPanel> panel) { _parentPanel = panel; }
|
void setParentPanel(std::shared_ptr<OverlayPanel> panel) { _parentPanel = panel; }
|
||||||
|
#endif
|
||||||
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
||||||
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
||||||
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
||||||
|
@ -66,7 +71,9 @@ protected:
|
||||||
quint64 _transformExpiry = 0;
|
quint64 _transformExpiry = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#if OVERLAY_PANELS
|
||||||
std::shared_ptr<OverlayPanel> _parentPanel = nullptr;
|
std::shared_ptr<OverlayPanel> _parentPanel = nullptr;
|
||||||
|
#endif
|
||||||
Transform _offset;
|
Transform _offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,21 +32,20 @@ QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay)
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlOverlay::buildQmlElement(const QUrl& url) {
|
void QmlOverlay::buildQmlElement(const QUrl& url) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "buildQmlElement", Q_ARG(QUrl, url));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
offscreenUi->returnFromUiThread([=] {
|
offscreenUi->load(url, [=](QQmlContext* context, QObject* object) {
|
||||||
offscreenUi->load(url, [=](QQmlContext* context, QObject* object) {
|
QQuickItem* rawPtr = dynamic_cast<QQuickItem*>(object);
|
||||||
QQuickItem* rawPtr = dynamic_cast<QQuickItem*>(object);
|
// Create a shared ptr with a custom deleter lambda, that calls deleteLater
|
||||||
// Create a shared ptr with a custom deleter lambda, that calls deleteLater
|
_qmlElement = std::shared_ptr<QQuickItem>(rawPtr, [](QQuickItem* ptr) {
|
||||||
_qmlElement = std::shared_ptr<QQuickItem>(rawPtr, [](QQuickItem* ptr) {
|
if (ptr) {
|
||||||
if (ptr) {
|
ptr->deleteLater();
|
||||||
ptr->deleteLater();
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
while (!_qmlElement) {
|
|
||||||
qApp->processEvents();
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,20 +54,23 @@ QmlOverlay::~QmlOverlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlOverlay::setProperties(const QVariantMap& properties) {
|
void QmlOverlay::setProperties(const QVariantMap& properties) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "setProperties", Q_ARG(QVariantMap, properties));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Overlay2D::setProperties(properties);
|
Overlay2D::setProperties(properties);
|
||||||
auto bounds = _bounds;
|
auto bounds = _bounds;
|
||||||
std::weak_ptr<QQuickItem> weakQmlElement = _qmlElement;
|
std::weak_ptr<QQuickItem> weakQmlElement = _qmlElement;
|
||||||
DependencyManager::get<OffscreenUi>()->executeOnUiThread([weakQmlElement, bounds, properties] {
|
// check to see if qmlElement still exists
|
||||||
// check to see if qmlElement still exists
|
auto qmlElement = weakQmlElement.lock();
|
||||||
auto qmlElement = weakQmlElement.lock();
|
if (qmlElement) {
|
||||||
if (qmlElement) {
|
qmlElement->setX(bounds.left());
|
||||||
qmlElement->setX(bounds.left());
|
qmlElement->setY(bounds.top());
|
||||||
qmlElement->setY(bounds.top());
|
qmlElement->setWidth(bounds.width());
|
||||||
qmlElement->setWidth(bounds.width());
|
qmlElement->setHeight(bounds.height());
|
||||||
qmlElement->setHeight(bounds.height());
|
QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties));
|
||||||
QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties));
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlOverlay::render(RenderArgs* args) {
|
void QmlOverlay::render(RenderArgs* args) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
void render(RenderArgs* args) override;
|
void render(RenderArgs* args) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void buildQmlElement(const QUrl& url);
|
Q_INVOKABLE void buildQmlElement(const QUrl& url);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<QQuickItem> _qmlElement;
|
std::shared_ptr<QQuickItem> _qmlElement;
|
||||||
|
|
|
@ -9,15 +9,18 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "AnimationCache.h"
|
||||||
|
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include "AnimationCache.h"
|
#include <shared/QtHelpers.h>
|
||||||
#include "AnimationLogging.h"
|
|
||||||
#include <Trace.h>
|
#include <Trace.h>
|
||||||
#include <StatTracker.h>
|
#include <StatTracker.h>
|
||||||
#include <Profile.h>
|
#include <Profile.h>
|
||||||
|
|
||||||
|
#include "AnimationLogging.h"
|
||||||
|
|
||||||
int animationPointerMetaTypeId = qRegisterMetaType<AnimationPointer>();
|
int animationPointerMetaTypeId = qRegisterMetaType<AnimationPointer>();
|
||||||
|
|
||||||
AnimationCache::AnimationCache(QObject* parent) :
|
AnimationCache::AnimationCache(QObject* parent) :
|
||||||
|
@ -31,7 +34,7 @@ AnimationCache::AnimationCache(QObject* parent) :
|
||||||
AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
|
AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
AnimationPointer result;
|
AnimationPointer result;
|
||||||
QMetaObject::invokeMethod(this, "getAnimation", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "getAnimation",
|
||||||
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
|
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +100,7 @@ bool Animation::isLoaded() const {
|
||||||
QStringList Animation::getJointNames() const {
|
QStringList Animation::getJointNames() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(const_cast<Animation*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Animation*>(this), "getJointNames",
|
||||||
Q_RETURN_ARG(QStringList, result));
|
Q_RETURN_ARG(QStringList, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +114,7 @@ QStringList Animation::getJointNames() const {
|
||||||
QVector<FBXAnimationFrame> Animation::getFrames() const {
|
QVector<FBXAnimationFrame> Animation::getFrames() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVector<FBXAnimationFrame> result;
|
QVector<FBXAnimationFrame> result;
|
||||||
QMetaObject::invokeMethod(const_cast<Animation*>(this), "getFrames", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Animation*>(this), "getFrames",
|
||||||
Q_RETURN_ARG(QVector<FBXAnimationFrame>, result));
|
Q_RETURN_ARG(QVector<FBXAnimationFrame>, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,10 +259,21 @@ void AudioClient::customDeleter() {
|
||||||
void AudioClient::cleanupBeforeQuit() {
|
void AudioClient::cleanupBeforeQuit() {
|
||||||
// FIXME: this should be put in customDeleter, but there is still a reference to this when it is called,
|
// FIXME: this should be put in customDeleter, but there is still a reference to this when it is called,
|
||||||
// so this must be explicitly, synchronously stopped
|
// so this must be explicitly, synchronously stopped
|
||||||
|
static ConditionalGuard guard;
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
// This will likely be called from the main thread, but we don't want to do blocking queued calls
|
||||||
|
// from the main thread, so we use a normal auto-connection invoke, and then use a conditional to wait
|
||||||
|
// for completion
|
||||||
|
// The effect is the same, yes, but we actually want to avoid the use of Qt::BlockingQueuedConnection
|
||||||
|
// in the code
|
||||||
|
QMetaObject::invokeMethod(this, "cleanupBeforeQuit");
|
||||||
|
guard.wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
_checkDevicesTimer->stop();
|
_checkDevicesTimer->stop();
|
||||||
|
guard.trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) {
|
void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) {
|
||||||
|
@ -1335,6 +1346,14 @@ void AudioClient::toggleMute() {
|
||||||
emit muteToggled();
|
emit muteToggled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioClient::setNoiseReduction(bool enable) {
|
||||||
|
if (_isNoiseGateEnabled != enable) {
|
||||||
|
_isNoiseGateEnabled = enable;
|
||||||
|
emit noiseReductionChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AudioClient::setIsStereoInput(bool isStereoInput) {
|
void AudioClient::setIsStereoInput(bool isStereoInput) {
|
||||||
if (isStereoInput != _isStereoInput) {
|
if (isStereoInput != _isStereoInput) {
|
||||||
_isStereoInput = isStereoInput;
|
_isStereoInput = isStereoInput;
|
||||||
|
@ -1446,6 +1465,8 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
|
||||||
_audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this);
|
_audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this);
|
||||||
_numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat);
|
_numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat);
|
||||||
_audioInput->setBufferSize(_numInputCallbackBytes);
|
_audioInput->setBufferSize(_numInputCallbackBytes);
|
||||||
|
// different audio input devices may have different volumes
|
||||||
|
emit inputVolumeChanged(_audioInput->volume());
|
||||||
|
|
||||||
// how do we want to handle input working, but output not working?
|
// how do we want to handle input working, but output not working?
|
||||||
int numFrameSamples = calculateNumberOfFrameSamples(_numInputCallbackBytes);
|
int numFrameSamples = calculateNumberOfFrameSamples(_numInputCallbackBytes);
|
||||||
|
@ -1703,7 +1724,7 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) {
|
||||||
|
|
||||||
// produce an oriented angle about the y-axis
|
// produce an oriented angle about the y-axis
|
||||||
glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2));
|
glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2));
|
||||||
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
|
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
|
||||||
return (direction.x < 0.0f) ? -angle : angle;
|
return (direction.x < 0.0f) ? -angle : angle;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1847,3 +1868,10 @@ void AudioClient::setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 sca
|
||||||
void AudioClient::startThread() {
|
void AudioClient::startThread() {
|
||||||
moveToNewNamedThread(this, "Audio Thread", [this] { start(); });
|
moveToNewNamedThread(this, "Audio Thread", [this] { start(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioClient::setInputVolume(float volume) {
|
||||||
|
if (_audioInput && volume != (float)_audioInput->volume()) {
|
||||||
|
_audioInput->setVolume(volume);
|
||||||
|
emit inputVolumeChanged(_audioInput->volume());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -180,7 +180,8 @@ public slots:
|
||||||
|
|
||||||
virtual void setIsStereoInput(bool stereo) override;
|
virtual void setIsStereoInput(bool stereo) override;
|
||||||
|
|
||||||
void setNoiseReduction(bool isNoiseGateEnabled) { _isNoiseGateEnabled = isNoiseGateEnabled; }
|
void setNoiseReduction(bool isNoiseGateEnabled);
|
||||||
|
bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; }
|
||||||
|
|
||||||
void toggleLocalEcho() { _shouldEchoLocally = !_shouldEchoLocally; }
|
void toggleLocalEcho() { _shouldEchoLocally = !_shouldEchoLocally; }
|
||||||
void toggleServerEcho() { _shouldEchoToServer = !_shouldEchoToServer; }
|
void toggleServerEcho() { _shouldEchoToServer = !_shouldEchoToServer; }
|
||||||
|
@ -197,7 +198,7 @@ public slots:
|
||||||
bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName);
|
bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName);
|
||||||
|
|
||||||
float getInputVolume() const { return (_audioInput) ? (float)_audioInput->volume() : 0.0f; }
|
float getInputVolume() const { return (_audioInput) ? (float)_audioInput->volume() : 0.0f; }
|
||||||
void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); }
|
void setInputVolume(float volume);
|
||||||
void setReverb(bool reverb);
|
void setReverb(bool reverb);
|
||||||
void setReverbOptions(const AudioEffectOptions* options);
|
void setReverbOptions(const AudioEffectOptions* options);
|
||||||
|
|
||||||
|
@ -207,7 +208,9 @@ public slots:
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
bool muteToggled();
|
void inputVolumeChanged(float volume);
|
||||||
|
void muteToggled();
|
||||||
|
void noiseReductionChanged();
|
||||||
void mutedByMixer();
|
void mutedByMixer();
|
||||||
void inputReceived(const QByteArray& inputSamples);
|
void inputReceived(const QByteArray& inputSamples);
|
||||||
void inputLoudnessChanged(float loudness);
|
void inputLoudnessChanged(float loudness);
|
||||||
|
|
|
@ -9,10 +9,13 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <qthread.h>
|
#include "SoundCache.h"
|
||||||
|
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
#include "AudioLogging.h"
|
#include "AudioLogging.h"
|
||||||
#include "SoundCache.h"
|
|
||||||
|
|
||||||
static const int SOUNDS_LOADING_PRIORITY { -7 }; // Make sure sounds load after the low rez texture mips
|
static const int SOUNDS_LOADING_PRIORITY { -7 }; // Make sure sounds load after the low rez texture mips
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ SoundCache::SoundCache(QObject* parent) :
|
||||||
SharedSoundPointer SoundCache::getSound(const QUrl& url) {
|
SharedSoundPointer SoundCache::getSound(const QUrl& url) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
SharedSoundPointer result;
|
SharedSoundPointer result;
|
||||||
QMetaObject::invokeMethod(this, "getSound", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "getSound",
|
||||||
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
|
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
#include <glm/gtx/vector_query.hpp>
|
#include <glm/gtx/vector_query.hpp>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <DeferredLightingEffect.h>
|
#include <DeferredLightingEffect.h>
|
||||||
#include <EntityTreeRenderer.h>
|
#include <EntityTreeRenderer.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
|
@ -1010,7 +1011,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
||||||
int Avatar::getJointIndex(const QString& name) const {
|
int Avatar::getJointIndex(const QString& name) const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
int result;
|
int result;
|
||||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointIndex", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Avatar*>(this), "getJointIndex",
|
||||||
Q_RETURN_ARG(int, result), Q_ARG(const QString&, name));
|
Q_RETURN_ARG(int, result), Q_ARG(const QString&, name));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1024,7 +1025,7 @@ int Avatar::getJointIndex(const QString& name) const {
|
||||||
QStringList Avatar::getJointNames() const {
|
QStringList Avatar::getJointNames() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Avatar*>(this), "getJointNames",
|
||||||
Q_RETURN_ARG(QStringList, result));
|
Q_RETURN_ARG(QStringList, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1034,7 +1035,7 @@ QStringList Avatar::getJointNames() const {
|
||||||
glm::vec3 Avatar::getJointPosition(int index) const {
|
glm::vec3 Avatar::getJointPosition(int index) const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointPosition", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Avatar*>(this), "getJointPosition",
|
||||||
Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index));
|
Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index));
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1047,7 @@ glm::vec3 Avatar::getJointPosition(int index) const {
|
||||||
glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointPosition", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Avatar*>(this), "getJointPosition",
|
||||||
Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name));
|
Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name));
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
@ -1105,7 +1106,7 @@ static std::shared_ptr<Model> allocateAttachmentModel(bool isSoft, const Rig& ri
|
||||||
|
|
||||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "setAttachmentData", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
#include <QtNetwork/QNetworkRequest>
|
#include <QtNetwork/QNetworkRequest>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <QVariantGLM.h>
|
#include <QVariantGLM.h>
|
||||||
#include <Transform.h>
|
#include <Transform.h>
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
|
@ -1227,7 +1228,7 @@ bool AvatarData::isJointDataValid(int index) const {
|
||||||
}
|
}
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "isJointDataValid", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "isJointDataValid",
|
||||||
Q_RETURN_ARG(bool, result), Q_ARG(int, index));
|
Q_RETURN_ARG(bool, result), Q_ARG(int, index));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1240,7 +1241,7 @@ glm::quat AvatarData::getJointRotation(int index) const {
|
||||||
}
|
}
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
glm::quat result;
|
glm::quat result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getJointRotation", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointRotation",
|
||||||
Q_RETURN_ARG(glm::quat, result), Q_ARG(int, index));
|
Q_RETURN_ARG(glm::quat, result), Q_ARG(int, index));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1255,7 +1256,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const {
|
||||||
}
|
}
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
glm::vec3 result;
|
glm::vec3 result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getJointTranslation", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointTranslation",
|
||||||
Q_RETURN_ARG(glm::vec3, result), Q_ARG(int, index));
|
Q_RETURN_ARG(glm::vec3, result), Q_ARG(int, index));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1266,7 +1267,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const {
|
||||||
glm::vec3 AvatarData::getJointTranslation(const QString& name) const {
|
glm::vec3 AvatarData::getJointTranslation(const QString& name) const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
glm::vec3 result;
|
glm::vec3 result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getJointTranslation", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointTranslation",
|
||||||
Q_RETURN_ARG(glm::vec3, result), Q_ARG(const QString&, name));
|
Q_RETURN_ARG(glm::vec3, result), Q_ARG(const QString&, name));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1345,7 @@ void AvatarData::clearJointData(const QString& name) {
|
||||||
bool AvatarData::isJointDataValid(const QString& name) const {
|
bool AvatarData::isJointDataValid(const QString& name) const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "isJointDataValid", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "isJointDataValid",
|
||||||
Q_RETURN_ARG(bool, result), Q_ARG(const QString&, name));
|
Q_RETURN_ARG(bool, result), Q_ARG(const QString&, name));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1354,7 +1355,7 @@ bool AvatarData::isJointDataValid(const QString& name) const {
|
||||||
glm::quat AvatarData::getJointRotation(const QString& name) const {
|
glm::quat AvatarData::getJointRotation(const QString& name) const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
glm::quat result;
|
glm::quat result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getJointRotation", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointRotation",
|
||||||
Q_RETURN_ARG(glm::quat, result), Q_ARG(const QString&, name));
|
Q_RETURN_ARG(glm::quat, result), Q_ARG(const QString&, name));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1364,8 +1365,7 @@ glm::quat AvatarData::getJointRotation(const QString& name) const {
|
||||||
QVector<glm::quat> AvatarData::getJointRotations() const {
|
QVector<glm::quat> AvatarData::getJointRotations() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVector<glm::quat> result;
|
QVector<glm::quat> result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointRotations",
|
||||||
"getJointRotations", Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QVector<glm::quat>, result));
|
Q_RETURN_ARG(QVector<glm::quat>, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1380,8 +1380,7 @@ QVector<glm::quat> AvatarData::getJointRotations() const {
|
||||||
void AvatarData::setJointRotations(QVector<glm::quat> jointRotations) {
|
void AvatarData::setJointRotations(QVector<glm::quat> jointRotations) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVector<glm::quat> result;
|
QVector<glm::quat> result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "setJointRotations",
|
||||||
"setJointRotations", Qt::BlockingQueuedConnection,
|
|
||||||
Q_ARG(QVector<glm::quat>, jointRotations));
|
Q_ARG(QVector<glm::quat>, jointRotations));
|
||||||
}
|
}
|
||||||
QWriteLocker writeLock(&_jointDataLock);
|
QWriteLocker writeLock(&_jointDataLock);
|
||||||
|
@ -1398,8 +1397,7 @@ void AvatarData::setJointRotations(QVector<glm::quat> jointRotations) {
|
||||||
QVector<glm::vec3> AvatarData::getJointTranslations() const {
|
QVector<glm::vec3> AvatarData::getJointTranslations() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVector<glm::vec3> result;
|
QVector<glm::vec3> result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointTranslations",
|
||||||
"getJointTranslations", Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QVector<glm::vec3>, result));
|
Q_RETURN_ARG(QVector<glm::vec3>, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1414,8 +1412,7 @@ QVector<glm::vec3> AvatarData::getJointTranslations() const {
|
||||||
void AvatarData::setJointTranslations(QVector<glm::vec3> jointTranslations) {
|
void AvatarData::setJointTranslations(QVector<glm::vec3> jointTranslations) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVector<glm::quat> result;
|
QVector<glm::quat> result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "setJointTranslations",
|
||||||
"setJointTranslations", Qt::BlockingQueuedConnection,
|
|
||||||
Q_ARG(QVector<glm::vec3>, jointTranslations));
|
Q_ARG(QVector<glm::vec3>, jointTranslations));
|
||||||
}
|
}
|
||||||
QWriteLocker writeLock(&_jointDataLock);
|
QWriteLocker writeLock(&_jointDataLock);
|
||||||
|
@ -1616,7 +1613,7 @@ void AvatarData::setDisplayName(const QString& displayName) {
|
||||||
QVector<AttachmentData> AvatarData::getAttachmentData() const {
|
QVector<AttachmentData> AvatarData::getAttachmentData() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVector<AttachmentData> result;
|
QVector<AttachmentData> result;
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAttachmentData", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getAttachmentData",
|
||||||
Q_RETURN_ARG(QVector<AttachmentData>, result));
|
Q_RETURN_ARG(QVector<AttachmentData>, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1978,7 +1975,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) {
|
||||||
result.rotation = quatFromJsonValue(array[0]);
|
result.rotation = quatFromJsonValue(array[0]);
|
||||||
result.rotationSet = true;
|
result.rotationSet = true;
|
||||||
result.translation = vec3FromJsonValue(array[1]);
|
result.translation = vec3FromJsonValue(array[1]);
|
||||||
result.translationSet = false;
|
result.translationSet = true;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2146,12 +2143,9 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
||||||
QVector<JointData> jointArray;
|
QVector<JointData> jointArray;
|
||||||
QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray();
|
QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray();
|
||||||
jointArray.reserve(jointArrayJson.size());
|
jointArray.reserve(jointArrayJson.size());
|
||||||
int i = 0;
|
|
||||||
for (const auto& jointJson : jointArrayJson) {
|
for (const auto& jointJson : jointArrayJson) {
|
||||||
auto joint = jointDataFromJsonValue(jointJson);
|
auto joint = jointDataFromJsonValue(jointJson);
|
||||||
jointArray.push_back(joint);
|
jointArray.push_back(joint);
|
||||||
setJointData(i, joint.rotation, joint.translation);
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
setRawJointData(jointArray);
|
setRawJointData(jointArray);
|
||||||
}
|
}
|
||||||
|
@ -2342,7 +2336,7 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID) {
|
||||||
AvatarEntityMap AvatarData::getAvatarEntityData() const {
|
AvatarEntityMap AvatarData::getAvatarEntityData() const {
|
||||||
AvatarEntityMap result;
|
AvatarEntityMap result;
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAvatarEntityData", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getAvatarEntityData",
|
||||||
Q_RETURN_ARG(AvatarEntityMap, result));
|
Q_RETURN_ARG(AvatarEntityMap, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2383,7 +2377,7 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
|
||||||
AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() {
|
AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() {
|
||||||
AvatarEntityIDs result;
|
AvatarEntityIDs result;
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getAndClearRecentlyDetachedIDs", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getAndClearRecentlyDetachedIDs",
|
||||||
Q_RETURN_ARG(AvatarEntityIDs, result));
|
Q_RETURN_ARG(AvatarEntityIDs, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -627,6 +627,7 @@ public:
|
||||||
void markIdentityDataChanged() { _identityDataChanged = true; }
|
void markIdentityDataChanged() { _identityDataChanged = true; }
|
||||||
|
|
||||||
void pushIdentitySequenceNumber() { ++_identitySequenceNumber; };
|
void pushIdentitySequenceNumber() { ++_identitySequenceNumber; };
|
||||||
|
bool hasProcessedFirstIdentity() const { return _hasProcessedFirstIdentity; }
|
||||||
|
|
||||||
float getDensity() const { return _density; }
|
float getDensity() const { return _density; }
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,48 @@ namespace controller {
|
||||||
makePosePair(Action::SPINE2, "Spine2"),
|
makePosePair(Action::SPINE2, "Spine2"),
|
||||||
makePosePair(Action::HEAD, "Head"),
|
makePosePair(Action::HEAD, "Head"),
|
||||||
|
|
||||||
|
makePosePair(Action::LEFT_HAND_THUMB1, "LeftHandThumb1"),
|
||||||
|
makePosePair(Action::LEFT_HAND_THUMB2, "LeftHandThumb2"),
|
||||||
|
makePosePair(Action::LEFT_HAND_THUMB3, "LeftHandThumb3"),
|
||||||
|
makePosePair(Action::LEFT_HAND_THUMB4, "LeftHandThumb4"),
|
||||||
|
makePosePair(Action::LEFT_HAND_INDEX1, "LeftHandIndex1"),
|
||||||
|
makePosePair(Action::LEFT_HAND_INDEX2, "LeftHandIndex2"),
|
||||||
|
makePosePair(Action::LEFT_HAND_INDEX3, "LeftHandIndex3"),
|
||||||
|
makePosePair(Action::LEFT_HAND_INDEX4, "LeftHandIndex4"),
|
||||||
|
makePosePair(Action::LEFT_HAND_MIDDLE1, "LeftHandMiddle1"),
|
||||||
|
makePosePair(Action::LEFT_HAND_MIDDLE2, "LeftHandMiddle2"),
|
||||||
|
makePosePair(Action::LEFT_HAND_MIDDLE3, "LeftHandMiddle3"),
|
||||||
|
makePosePair(Action::LEFT_HAND_MIDDLE4, "LeftHandMiddle4"),
|
||||||
|
makePosePair(Action::LEFT_HAND_RING1, "LeftHandRing1"),
|
||||||
|
makePosePair(Action::LEFT_HAND_RING2, "LeftHandRing2"),
|
||||||
|
makePosePair(Action::LEFT_HAND_RING3, "LeftHandRing3"),
|
||||||
|
makePosePair(Action::LEFT_HAND_RING4, "LeftHandRing4"),
|
||||||
|
makePosePair(Action::LEFT_HAND_PINKY1, "LeftHandPinky1"),
|
||||||
|
makePosePair(Action::LEFT_HAND_PINKY2, "LeftHandPinky2"),
|
||||||
|
makePosePair(Action::LEFT_HAND_PINKY3, "LeftHandPinky3"),
|
||||||
|
makePosePair(Action::LEFT_HAND_PINKY4, "LeftHandPinky4"),
|
||||||
|
|
||||||
|
makePosePair(Action::RIGHT_HAND_THUMB1, "RightHandThumb1"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_THUMB2, "RightHandThumb2"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_THUMB3, "RightHandThumb3"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_THUMB4, "RightHandThumb4"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_INDEX1, "RightHandIndex1"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_INDEX2, "RightHandIndex2"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_INDEX3, "RightHandIndex3"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_INDEX4, "RightHandIndex4"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_MIDDLE1, "RightHandMiddle1"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_MIDDLE2, "RightHandMiddle2"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_MIDDLE3, "RightHandMiddle3"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_MIDDLE4, "RightHandMiddle4"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_RING1, "RightHandRing1"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_RING2, "RightHandRing2"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_RING3, "RightHandRing3"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_RING4, "RightHandRing4"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_PINKY1, "RightHandPinky1"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_PINKY2, "RightHandPinky2"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_PINKY3, "RightHandPinky3"),
|
||||||
|
makePosePair(Action::RIGHT_HAND_PINKY4, "RightHandPinky4"),
|
||||||
|
|
||||||
makeButtonPair(Action::LEFT_HAND_CLICK, "LeftHandClick"),
|
makeButtonPair(Action::LEFT_HAND_CLICK, "LeftHandClick"),
|
||||||
makeButtonPair(Action::RIGHT_HAND_CLICK, "RightHandClick"),
|
makeButtonPair(Action::RIGHT_HAND_CLICK, "RightHandClick"),
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,47 @@ enum class Action {
|
||||||
LEFT_ARM,
|
LEFT_ARM,
|
||||||
RIGHT_ARM,
|
RIGHT_ARM,
|
||||||
|
|
||||||
|
LEFT_HAND_THUMB1,
|
||||||
|
LEFT_HAND_THUMB2,
|
||||||
|
LEFT_HAND_THUMB3,
|
||||||
|
LEFT_HAND_THUMB4,
|
||||||
|
LEFT_HAND_INDEX1,
|
||||||
|
LEFT_HAND_INDEX2,
|
||||||
|
LEFT_HAND_INDEX3,
|
||||||
|
LEFT_HAND_INDEX4,
|
||||||
|
LEFT_HAND_MIDDLE1,
|
||||||
|
LEFT_HAND_MIDDLE2,
|
||||||
|
LEFT_HAND_MIDDLE3,
|
||||||
|
LEFT_HAND_MIDDLE4,
|
||||||
|
LEFT_HAND_RING1,
|
||||||
|
LEFT_HAND_RING2,
|
||||||
|
LEFT_HAND_RING3,
|
||||||
|
LEFT_HAND_RING4,
|
||||||
|
LEFT_HAND_PINKY1,
|
||||||
|
LEFT_HAND_PINKY2,
|
||||||
|
LEFT_HAND_PINKY3,
|
||||||
|
LEFT_HAND_PINKY4,
|
||||||
|
|
||||||
|
RIGHT_HAND_THUMB1,
|
||||||
|
RIGHT_HAND_THUMB2,
|
||||||
|
RIGHT_HAND_THUMB3,
|
||||||
|
RIGHT_HAND_THUMB4,
|
||||||
|
RIGHT_HAND_INDEX1,
|
||||||
|
RIGHT_HAND_INDEX2,
|
||||||
|
RIGHT_HAND_INDEX3,
|
||||||
|
RIGHT_HAND_INDEX4,
|
||||||
|
RIGHT_HAND_MIDDLE1,
|
||||||
|
RIGHT_HAND_MIDDLE2,
|
||||||
|
RIGHT_HAND_MIDDLE3,
|
||||||
|
RIGHT_HAND_MIDDLE4,
|
||||||
|
RIGHT_HAND_RING1,
|
||||||
|
RIGHT_HAND_RING2,
|
||||||
|
RIGHT_HAND_RING3,
|
||||||
|
RIGHT_HAND_RING4,
|
||||||
|
RIGHT_HAND_PINKY1,
|
||||||
|
RIGHT_HAND_PINKY2,
|
||||||
|
RIGHT_HAND_PINKY3,
|
||||||
|
RIGHT_HAND_PINKY4,
|
||||||
|
|
||||||
NUM_ACTIONS,
|
NUM_ACTIONS,
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,7 +101,47 @@ Input::NamedVector StandardController::getAvailableInputs() const {
|
||||||
|
|
||||||
// Poses
|
// Poses
|
||||||
makePair(LEFT_HAND, "LeftHand"),
|
makePair(LEFT_HAND, "LeftHand"),
|
||||||
|
makePair(LEFT_HAND_THUMB1, "LeftHandThumb1"),
|
||||||
|
makePair(LEFT_HAND_THUMB2, "LeftHandThumb2"),
|
||||||
|
makePair(LEFT_HAND_THUMB3, "LeftHandThumb3"),
|
||||||
|
makePair(LEFT_HAND_THUMB4, "LeftHandThumb4"),
|
||||||
|
makePair(LEFT_HAND_INDEX1, "LeftHandIndex1"),
|
||||||
|
makePair(LEFT_HAND_INDEX2, "LeftHandIndex2"),
|
||||||
|
makePair(LEFT_HAND_INDEX3, "LeftHandIndex3"),
|
||||||
|
makePair(LEFT_HAND_INDEX4, "LeftHandIndex4"),
|
||||||
|
makePair(LEFT_HAND_MIDDLE1, "LeftHandMiddle1"),
|
||||||
|
makePair(LEFT_HAND_MIDDLE2, "LeftHandMiddle2"),
|
||||||
|
makePair(LEFT_HAND_MIDDLE3, "LeftHandMiddle3"),
|
||||||
|
makePair(LEFT_HAND_MIDDLE4, "LeftHandMiddle4"),
|
||||||
|
makePair(LEFT_HAND_RING1, "LeftHandRing1"),
|
||||||
|
makePair(LEFT_HAND_RING2, "LeftHandRing2"),
|
||||||
|
makePair(LEFT_HAND_RING3, "LeftHandRing3"),
|
||||||
|
makePair(LEFT_HAND_RING4, "LeftHandRing4"),
|
||||||
|
makePair(LEFT_HAND_PINKY1, "LeftHandPinky1"),
|
||||||
|
makePair(LEFT_HAND_PINKY2, "LeftHandPinky2"),
|
||||||
|
makePair(LEFT_HAND_PINKY3, "LeftHandPinky3"),
|
||||||
|
makePair(LEFT_HAND_PINKY4, "LeftHandPinky4"),
|
||||||
makePair(RIGHT_HAND, "RightHand"),
|
makePair(RIGHT_HAND, "RightHand"),
|
||||||
|
makePair(RIGHT_HAND_THUMB1, "RightHandThumb1"),
|
||||||
|
makePair(RIGHT_HAND_THUMB2, "RightHandThumb2"),
|
||||||
|
makePair(RIGHT_HAND_THUMB3, "RightHandThumb3"),
|
||||||
|
makePair(RIGHT_HAND_THUMB4, "RightHandThumb4"),
|
||||||
|
makePair(RIGHT_HAND_INDEX1, "RightHandIndex1"),
|
||||||
|
makePair(RIGHT_HAND_INDEX2, "RightHandIndex2"),
|
||||||
|
makePair(RIGHT_HAND_INDEX3, "RightHandIndex3"),
|
||||||
|
makePair(RIGHT_HAND_INDEX4, "RightHandIndex4"),
|
||||||
|
makePair(RIGHT_HAND_MIDDLE1, "RightHandMiddle1"),
|
||||||
|
makePair(RIGHT_HAND_MIDDLE2, "RightHandMiddle2"),
|
||||||
|
makePair(RIGHT_HAND_MIDDLE3, "RightHandMiddle3"),
|
||||||
|
makePair(RIGHT_HAND_MIDDLE4, "RightHandMiddle4"),
|
||||||
|
makePair(RIGHT_HAND_RING1, "RightHandRing1"),
|
||||||
|
makePair(RIGHT_HAND_RING2, "RightHandRing2"),
|
||||||
|
makePair(RIGHT_HAND_RING3, "RightHandRing3"),
|
||||||
|
makePair(RIGHT_HAND_RING4, "RightHandRing4"),
|
||||||
|
makePair(RIGHT_HAND_PINKY1, "RightHandPinky1"),
|
||||||
|
makePair(RIGHT_HAND_PINKY2, "RightHandPinky2"),
|
||||||
|
makePair(RIGHT_HAND_PINKY3, "RightHandPinky3"),
|
||||||
|
makePair(RIGHT_HAND_PINKY4, "RightHandPinky4"),
|
||||||
makePair(LEFT_FOOT, "LeftFoot"),
|
makePair(LEFT_FOOT, "LeftFoot"),
|
||||||
makePair(RIGHT_FOOT, "RightFoot"),
|
makePair(RIGHT_FOOT, "RightFoot"),
|
||||||
makePair(RIGHT_ARM, "RightArm"),
|
makePair(RIGHT_ARM, "RightArm"),
|
||||||
|
|
|
@ -11,14 +11,16 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtWidgets/QDesktopWidget>
|
#include <QtWidgets/QDesktopWidget>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <ui/Menu.h>
|
#include <ui/Menu.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
@ -289,7 +291,7 @@ glm::vec2 CompositorHelper::getReticleMaximumPosition() const {
|
||||||
|
|
||||||
void CompositorHelper::sendFakeMouseEvent() {
|
void CompositorHelper::sendFakeMouseEvent() {
|
||||||
if (qApp->thread() != QThread::currentThread()) {
|
if (qApp->thread() != QThread::currentThread()) {
|
||||||
QMetaObject::invokeMethod(this, "sendFakeMouseEvent", Qt::BlockingQueuedConnection);
|
BLOCKING_INVOKE_METHOD(this, "sendFakeMouseEvent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <QScriptSyntaxCheckResult>
|
#include <QScriptSyntaxCheckResult>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <ColorUtils.h>
|
#include <ColorUtils.h>
|
||||||
#include <AbstractScriptingServicesInterface.h>
|
#include <AbstractScriptingServicesInterface.h>
|
||||||
#include <AbstractViewStateInterface.h>
|
#include <AbstractViewStateInterface.h>
|
||||||
|
@ -380,7 +381,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading
|
||||||
|
|
||||||
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "allocateModel", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "allocateModel",
|
||||||
Q_RETURN_ARG(ModelPointer, model),
|
Q_RETURN_ARG(ModelPointer, model),
|
||||||
Q_ARG(const QString&, url));
|
Q_ARG(const QString&, url));
|
||||||
|
|
||||||
|
@ -397,7 +398,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, float loading
|
||||||
ModelPointer EntityTreeRenderer::updateModel(ModelPointer model, const QString& newUrl) {
|
ModelPointer EntityTreeRenderer::updateModel(ModelPointer model, const QString& newUrl) {
|
||||||
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "updateModel", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "updateModel",
|
||||||
Q_RETURN_ARG(ModelPointer, model),
|
Q_RETURN_ARG(ModelPointer, model),
|
||||||
Q_ARG(ModelPointer, model),
|
Q_ARG(ModelPointer, model),
|
||||||
Q_ARG(const QString&, newUrl));
|
Q_ARG(const QString&, newUrl));
|
||||||
|
|
|
@ -9,19 +9,20 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "EntityScriptingInterface.h"
|
||||||
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
#include "EntityScriptingInterface.h"
|
|
||||||
|
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
|
|
||||||
#include "EntityItemID.h"
|
#include <shared/QtHelpers.h>
|
||||||
#include <VariantMapToScriptValue.h>
|
#include <VariantMapToScriptValue.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <SpatialParentFinder.h>
|
#include <SpatialParentFinder.h>
|
||||||
|
|
||||||
|
#include "EntityItemID.h"
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "EntityDynamicFactoryInterface.h"
|
#include "EntityDynamicFactoryInterface.h"
|
||||||
#include "EntityDynamicInterface.h"
|
#include "EntityDynamicInterface.h"
|
||||||
|
@ -1488,7 +1489,7 @@ int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int result;
|
int result;
|
||||||
QMetaObject::invokeMethod(_entityTree.get(), "getJointIndex", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointIndex",
|
||||||
Q_RETURN_ARG(int, result), Q_ARG(QUuid, entityID), Q_ARG(QString, name));
|
Q_RETURN_ARG(int, result), Q_ARG(QUuid, entityID), Q_ARG(QString, name));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1498,7 +1499,7 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) {
|
||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(_entityTree.get(), "getJointNames", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointNames",
|
||||||
Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID));
|
Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::gl::GLBackend::do_getQuery),
|
(&::gpu::gl::GLBackend::do_getQuery),
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_resetStages),
|
(&::gpu::gl::GLBackend::do_resetStages),
|
||||||
|
|
||||||
|
(&::gpu::gl::GLBackend::do_disableContextViewCorrection),
|
||||||
|
(&::gpu::gl::GLBackend::do_restoreContextViewCorrection),
|
||||||
(&::gpu::gl::GLBackend::do_disableContextStereo),
|
(&::gpu::gl::GLBackend::do_disableContextStereo),
|
||||||
(&::gpu::gl::GLBackend::do_restoreContextStereo),
|
(&::gpu::gl::GLBackend::do_restoreContextStereo),
|
||||||
|
|
||||||
|
@ -374,6 +376,13 @@ void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) {
|
||||||
resetStages();
|
resetStages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) {
|
||||||
|
_transform._viewCorrectionEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) {
|
||||||
|
_transform._viewCorrectionEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
void GLBackend::do_disableContextStereo(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_disableContextStereo(const Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,10 @@ public:
|
||||||
// Reset stages
|
// Reset stages
|
||||||
virtual void do_resetStages(const Batch& batch, size_t paramOffset) final;
|
virtual void do_resetStages(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final;
|
||||||
|
virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
virtual void do_disableContextStereo(const Batch& batch, size_t paramOffset) final;
|
virtual void do_disableContextStereo(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_restoreContextStereo(const Batch& batch, size_t paramOffset) final;
|
virtual void do_restoreContextStereo(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
|
@ -333,6 +337,8 @@ protected:
|
||||||
bool _skybox { false };
|
bool _skybox { false };
|
||||||
Transform _view;
|
Transform _view;
|
||||||
CameraCorrection _correction;
|
CameraCorrection _correction;
|
||||||
|
bool _viewCorrectionEnabled{ true };
|
||||||
|
|
||||||
|
|
||||||
Mat4 _projection;
|
Mat4 _projection;
|
||||||
Vec4i _viewport { 0, 0, 1, 1 };
|
Vec4i _viewport { 0, 0, 1, 1 };
|
||||||
|
@ -400,6 +406,7 @@ protected:
|
||||||
bool _invalidProgram { false };
|
bool _invalidProgram { false };
|
||||||
|
|
||||||
BufferView _cameraCorrectionBuffer { gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr )) };
|
BufferView _cameraCorrectionBuffer { gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr )) };
|
||||||
|
BufferView _cameraCorrectionBufferIdentity { gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(CameraCorrection), nullptr )) };
|
||||||
|
|
||||||
State::Data _stateCache{ State::DEFAULT };
|
State::Data _stateCache{ State::DEFAULT };
|
||||||
State::Signature _stateSignatureCache { 0 };
|
State::Signature _stateSignatureCache { 0 };
|
||||||
|
@ -409,6 +416,8 @@ protected:
|
||||||
|
|
||||||
PipelineStageState() {
|
PipelineStageState() {
|
||||||
_cameraCorrectionBuffer.edit<CameraCorrection>() = CameraCorrection();
|
_cameraCorrectionBuffer.edit<CameraCorrection>() = CameraCorrection();
|
||||||
|
_cameraCorrectionBufferIdentity.edit<CameraCorrection>() = CameraCorrection();
|
||||||
|
_cameraCorrectionBufferIdentity._buffer->flush();
|
||||||
}
|
}
|
||||||
} _pipeline;
|
} _pipeline;
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,14 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
||||||
if (_pipeline._invalidProgram) {
|
if (_pipeline._invalidProgram) {
|
||||||
glUseProgram(_pipeline._program);
|
glUseProgram(_pipeline._program);
|
||||||
if (_pipeline._cameraCorrectionLocation != -1) {
|
if (_pipeline._cameraCorrectionLocation != -1) {
|
||||||
auto cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer);
|
gl::GLBuffer* cameraCorrectionBuffer = nullptr;
|
||||||
|
if (_transform._viewCorrectionEnabled) {
|
||||||
|
cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer);
|
||||||
|
} else {
|
||||||
|
cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBufferIdentity._buffer);
|
||||||
|
}
|
||||||
glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection));
|
glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection));
|
||||||
|
|
||||||
}
|
}
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
_pipeline._invalidProgram = false;
|
_pipeline._invalidProgram = false;
|
||||||
|
|
|
@ -102,7 +102,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
||||||
|
|
||||||
if (_invalidView) {
|
if (_invalidView) {
|
||||||
// Apply the correction
|
// Apply the correction
|
||||||
if (_viewIsCamera && _correction.correction != glm::mat4()) {
|
if (_viewIsCamera && (_viewCorrectionEnabled && _correction.correction != glm::mat4())) {
|
||||||
// FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out?
|
// FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out?
|
||||||
Transform result;
|
Transform result;
|
||||||
_view.mult(result, _view, _correction.correction);
|
_view.mult(result, _view, _correction.correction);
|
||||||
|
|
|
@ -390,6 +390,13 @@ void Batch::resetStages() {
|
||||||
ADD_COMMAND(resetStages);
|
ADD_COMMAND(resetStages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::disableContextViewCorrection() {
|
||||||
|
ADD_COMMAND(disableContextViewCorrection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Batch::restoreContextViewCorrection() {
|
||||||
|
ADD_COMMAND(restoreContextViewCorrection);
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::disableContextStereo() {
|
void Batch::disableContextStereo() {
|
||||||
ADD_COMMAND(disableContextStereo);
|
ADD_COMMAND(disableContextStereo);
|
||||||
|
|
|
@ -217,6 +217,9 @@ public:
|
||||||
// Reset the stage caches and states
|
// Reset the stage caches and states
|
||||||
void resetStages();
|
void resetStages();
|
||||||
|
|
||||||
|
void disableContextViewCorrection();
|
||||||
|
void restoreContextViewCorrection();
|
||||||
|
|
||||||
void disableContextStereo();
|
void disableContextStereo();
|
||||||
void restoreContextStereo();
|
void restoreContextStereo();
|
||||||
|
|
||||||
|
@ -304,6 +307,9 @@ public:
|
||||||
|
|
||||||
COMMAND_resetStages,
|
COMMAND_resetStages,
|
||||||
|
|
||||||
|
COMMAND_disableContextViewCorrection,
|
||||||
|
COMMAND_restoreContextViewCorrection,
|
||||||
|
|
||||||
COMMAND_disableContextStereo,
|
COMMAND_disableContextStereo,
|
||||||
COMMAND_restoreContextStereo,
|
COMMAND_restoreContextStereo,
|
||||||
|
|
||||||
|
|
|
@ -198,11 +198,7 @@ gpu::TexturePointer TextureCache::getTextureByHash(const std::string& hash) {
|
||||||
std::unique_lock<std::mutex> lock(_texturesByHashesMutex);
|
std::unique_lock<std::mutex> lock(_texturesByHashesMutex);
|
||||||
weakPointer = _texturesByHashes[hash];
|
weakPointer = _texturesByHashes[hash];
|
||||||
}
|
}
|
||||||
auto result = weakPointer.lock();
|
return weakPointer.lock();
|
||||||
if (result) {
|
|
||||||
qCWarning(modelnetworking) << "QQQ Returning live texture for hash " << hash.c_str();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture) {
|
gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture) {
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
#include <QtNetwork/QNetworkDiskCache>
|
#include <QtNetwork/QNetworkDiskCache>
|
||||||
|
|
||||||
|
#include <shared/GlobalAppProperties.h>
|
||||||
|
|
||||||
#include "AssetRequest.h"
|
#include "AssetRequest.h"
|
||||||
#include "AssetUpload.h"
|
#include "AssetUpload.h"
|
||||||
#include "AssetUtils.h"
|
#include "AssetUtils.h"
|
||||||
|
@ -31,11 +33,12 @@
|
||||||
|
|
||||||
MessageID AssetClient::_currentID = 0;
|
MessageID AssetClient::_currentID = 0;
|
||||||
|
|
||||||
AssetClient::AssetClient(const QString& cacheDir) : _cacheDir(cacheDir) {
|
AssetClient::AssetClient() {
|
||||||
|
_cacheDir = qApp->property(hifi::properties::APP_LOCAL_DATA_PATH).toString();
|
||||||
setCustomDeleter([](Dependency* dependency){
|
setCustomDeleter([](Dependency* dependency){
|
||||||
static_cast<AssetClient*>(dependency)->deleteLater();
|
static_cast<AssetClient*>(dependency)->deleteLater();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||||
|
|
||||||
|
@ -105,7 +108,7 @@ void AssetClient::handleAssetMappingOperationReply(QSharedPointer<ReceivedMessag
|
||||||
|
|
||||||
MessageID messageID;
|
MessageID messageID;
|
||||||
message->readPrimitive(&messageID);
|
message->readPrimitive(&messageID);
|
||||||
|
|
||||||
AssetServerError error;
|
AssetServerError error;
|
||||||
message->readPrimitive(&error);
|
message->readPrimitive(&error);
|
||||||
|
|
||||||
|
@ -132,13 +135,13 @@ void AssetClient::handleAssetMappingOperationReply(QSharedPointer<ReceivedMessag
|
||||||
bool haveAssetServer() {
|
bool haveAssetServer() {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (!assetServer) {
|
if (!assetServer) {
|
||||||
qCWarning(asset_client) << "Could not complete AssetClient operation "
|
qCWarning(asset_client) << "Could not complete AssetClient operation "
|
||||||
<< "since you are not currently connected to an asset-server.";
|
<< "since you are not currently connected to an asset-server.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,14 +223,14 @@ MessageID AssetClient::getAsset(const QString& hash, DataOffset start, DataOffse
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
|
|
||||||
auto messageID = ++_currentID;
|
auto messageID = ++_currentID;
|
||||||
|
|
||||||
auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH + sizeof(start) + sizeof(end);
|
auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH + sizeof(start) + sizeof(end);
|
||||||
auto packet = NLPacket::create(PacketType::AssetGet, payloadSize, true);
|
auto packet = NLPacket::create(PacketType::AssetGet, payloadSize, true);
|
||||||
|
|
||||||
qCDebug(asset_client) << "Requesting data from" << start << "to" << end << "of" << hash << "from asset-server.";
|
qCDebug(asset_client) << "Requesting data from" << start << "to" << end << "of" << hash << "from asset-server.";
|
||||||
|
|
||||||
packet->writePrimitive(messageID);
|
packet->writePrimitive(messageID);
|
||||||
|
|
||||||
packet->write(QByteArray::fromHex(hash.toLatin1()));
|
packet->write(QByteArray::fromHex(hash.toLatin1()));
|
||||||
|
@ -254,10 +257,10 @@ MessageID AssetClient::getAssetInfo(const QString& hash, GetInfoCallback callbac
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
auto messageID = ++_currentID;
|
auto messageID = ++_currentID;
|
||||||
|
|
||||||
auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH;
|
auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH;
|
||||||
auto packet = NLPacket::create(PacketType::AssetGetInfo, payloadSize, true);
|
auto packet = NLPacket::create(PacketType::AssetGetInfo, payloadSize, true);
|
||||||
|
|
||||||
packet->writePrimitive(messageID);
|
packet->writePrimitive(messageID);
|
||||||
packet->write(QByteArray::fromHex(hash.toLatin1()));
|
packet->write(QByteArray::fromHex(hash.toLatin1()));
|
||||||
|
|
||||||
|
@ -278,7 +281,7 @@ void AssetClient::handleAssetGetInfoReply(QSharedPointer<ReceivedMessage> messag
|
||||||
MessageID messageID;
|
MessageID messageID;
|
||||||
message->readPrimitive(&messageID);
|
message->readPrimitive(&messageID);
|
||||||
auto assetHash = message->read(SHA256_HASH_LENGTH);
|
auto assetHash = message->read(SHA256_HASH_LENGTH);
|
||||||
|
|
||||||
AssetServerError error;
|
AssetServerError error;
|
||||||
message->readPrimitive(&error);
|
message->readPrimitive(&error);
|
||||||
|
|
||||||
|
@ -367,7 +370,7 @@ void AssetClient::handleAssetGetReply(QSharedPointer<ReceivedMessage> message, S
|
||||||
callbacks.completeCallback(true, error, message->readAll());
|
callbacks.completeCallback(true, error, message->readAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
messageCallbackMap.erase(requestIt);
|
messageCallbackMap.erase(requestIt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,7 +481,7 @@ MessageID AssetClient::getAllAssetMappings(MappingOperationCallback callback) {
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true);
|
auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true);
|
||||||
|
|
||||||
|
@ -501,7 +504,7 @@ MessageID AssetClient::getAllAssetMappings(MappingOperationCallback callback) {
|
||||||
MessageID AssetClient::deleteAssetMappings(const AssetPathList& paths, MappingOperationCallback callback) {
|
MessageID AssetClient::deleteAssetMappings(const AssetPathList& paths, MappingOperationCallback callback) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true);
|
auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true);
|
||||||
|
|
||||||
|
@ -532,7 +535,7 @@ MessageID AssetClient::setAssetMapping(const QString& path, const AssetHash& has
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true);
|
auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true);
|
||||||
|
|
||||||
|
@ -644,7 +647,7 @@ MessageID AssetClient::uploadAsset(const QByteArray& data, UploadResultCallback
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
|
||||||
if (assetServer) {
|
if (assetServer) {
|
||||||
auto packetList = NLPacketList::create(PacketType::AssetUpload, QByteArray(), true, true);
|
auto packetList = NLPacketList::create(PacketType::AssetUpload, QByteArray(), true, true);
|
||||||
|
|
||||||
|
@ -682,7 +685,7 @@ void AssetClient::handleAssetUploadReply(QSharedPointer<ReceivedMessage> message
|
||||||
} else {
|
} else {
|
||||||
auto hash = message->read(SHA256_HASH_LENGTH);
|
auto hash = message->read(SHA256_HASH_LENGTH);
|
||||||
hashString = hash.toHex();
|
hashString = hash.toHex();
|
||||||
|
|
||||||
qCDebug(asset_client) << "Successfully uploaded asset to asset-server - SHA256 hash is " << hashString;
|
qCDebug(asset_client) << "Successfully uploaded asset to asset-server - SHA256 hash is " << hashString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ using ProgressCallback = std::function<void(qint64 totalReceived, qint64 total)>
|
||||||
class AssetClient : public QObject, public Dependency {
|
class AssetClient : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
AssetClient(const QString& cacheDir="");
|
AssetClient();
|
||||||
|
|
||||||
Q_INVOKABLE GetMappingRequest* createGetMappingRequest(const AssetPath& path);
|
Q_INVOKABLE GetMappingRequest* createGetMappingRequest(const AssetPath& path);
|
||||||
Q_INVOKABLE GetAllMappingsRequest* createGetAllMappingsRequest();
|
Q_INVOKABLE GetAllMappingsRequest* createGetAllMappingsRequest();
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <QtNetwork/QHostInfo>
|
#include <QtNetwork/QHostInfo>
|
||||||
#include <QtNetwork/QNetworkInterface>
|
#include <QtNetwork/QNetworkInterface>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <ThreadHelpers.h>
|
#include <ThreadHelpers.h>
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
@ -232,7 +233,7 @@ void NodeList::processICEPingPacket(QSharedPointer<ReceivedMessage> message) {
|
||||||
|
|
||||||
void NodeList::reset() {
|
void NodeList::reset() {
|
||||||
if (thread() != QThread::currentThread()) {
|
if (thread() != QThread::currentThread()) {
|
||||||
QMetaObject::invokeMethod(this, "reset", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(this, "reset");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,22 +9,24 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "ResourceCache.h"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <assert.h>
|
#include <shared/QtHelpers.h>
|
||||||
|
#include <Trace.h>
|
||||||
|
#include <Profile.h>
|
||||||
|
|
||||||
#include "NetworkAccessManager.h"
|
#include "NetworkAccessManager.h"
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
|
|
||||||
#include "ResourceCache.h"
|
|
||||||
#include <Trace.h>
|
|
||||||
#include <Profile.h>
|
|
||||||
|
|
||||||
#define clamp(x, min, max) (((x) < (min)) ? (min) :\
|
#define clamp(x, min, max) (((x) < (min)) ? (min) :\
|
||||||
(((x) > (max)) ? (max) :\
|
(((x) > (max)) ? (max) :\
|
||||||
|
@ -178,7 +180,7 @@ ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) {
|
||||||
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
// Must be called in thread to ensure getResource returns a valid pointer
|
// Must be called in thread to ensure getResource returns a valid pointer
|
||||||
QMetaObject::invokeMethod(this, "prefetch", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "prefetch",
|
||||||
Q_RETURN_ARG(ScriptableResource*, result),
|
Q_RETURN_ARG(ScriptableResource*, result),
|
||||||
Q_ARG(QUrl, url), Q_ARG(void*, extra));
|
Q_ARG(QUrl, url), Q_ARG(void*, extra));
|
||||||
return result;
|
return result;
|
||||||
|
@ -301,7 +303,7 @@ QVariantList ResourceCache::getResourceList() {
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
// NOTE: invokeMethod does not allow a const QObject*
|
// NOTE: invokeMethod does not allow a const QObject*
|
||||||
QMetaObject::invokeMethod(this, "getResourceList", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "getResourceList",
|
||||||
Q_RETURN_ARG(QVariantList, list));
|
Q_RETURN_ARG(QVariantList, list));
|
||||||
} else {
|
} else {
|
||||||
auto resources = _resources.uniqueKeys();
|
auto resources = _resources.uniqueKeys();
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
ResourceManager::ResourceManager() {
|
ResourceManager::ResourceManager() {
|
||||||
_thread.setObjectName("Resource Manager Thread");
|
_thread.setObjectName("Resource Manager Thread");
|
||||||
|
|
||||||
auto assetClient = DependencyManager::set<AssetClient>(_cacheDir);
|
auto assetClient = DependencyManager::set<AssetClient>();
|
||||||
assetClient->moveToThread(&_thread);
|
assetClient->moveToThread(&_thread);
|
||||||
QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init);
|
QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init);
|
||||||
|
|
||||||
|
@ -160,7 +160,3 @@ bool ResourceManager::resourceExists(const QUrl& url) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::setCacheDir(const QString& cacheDir) {
|
|
||||||
// TODO: check for existence?
|
|
||||||
_cacheDir = cacheDir;
|
|
||||||
}
|
|
||||||
|
|
|
@ -59,7 +59,6 @@ private:
|
||||||
PrefixMap _prefixMap;
|
PrefixMap _prefixMap;
|
||||||
QMutex _prefixMapLock;
|
QMutex _prefixMapLock;
|
||||||
|
|
||||||
QString _cacheDir;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
|
|
||||||
#include "../NetworkLogging.h"
|
#include "../NetworkLogging.h"
|
||||||
|
@ -276,7 +277,7 @@ Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) {
|
||||||
|
|
||||||
void Socket::clearConnections() {
|
void Socket::clearConnections() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "clearConnections", Qt::BlockingQueuedConnection);
|
BLOCKING_INVOKE_METHOD(this, "clearConnections");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
#include "DisplayPlugin.h"
|
#include "DisplayPlugin.h"
|
||||||
#include "InputPlugin.h"
|
#include "InputPlugin.h"
|
||||||
#include "PluginManager.h"
|
#include "PluginManager.h"
|
||||||
|
@ -21,7 +23,7 @@ InputConfiguration::InputConfiguration() {
|
||||||
QStringList InputConfiguration::inputPlugins() {
|
QStringList InputConfiguration::inputPlugins() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(this, "inputPlugins", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "inputPlugins",
|
||||||
Q_RETURN_ARG(QStringList, result));
|
Q_RETURN_ARG(QStringList, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ QStringList InputConfiguration::inputPlugins() {
|
||||||
QStringList InputConfiguration::activeInputPlugins() {
|
QStringList InputConfiguration::activeInputPlugins() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(this, "activeInputPlugins", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "activeInputPlugins",
|
||||||
Q_RETURN_ARG(QStringList, result));
|
Q_RETURN_ARG(QStringList, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +66,7 @@ QStringList InputConfiguration::activeInputPlugins() {
|
||||||
QString InputConfiguration::configurationLayout(QString pluginName) {
|
QString InputConfiguration::configurationLayout(QString pluginName) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QString result;
|
QString result;
|
||||||
QMetaObject::invokeMethod(this, "configurationLayout", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "configurationLayout",
|
||||||
Q_RETURN_ARG(QString, result),
|
Q_RETURN_ARG(QString, result),
|
||||||
Q_ARG(QString, pluginName));
|
Q_ARG(QString, pluginName));
|
||||||
return result;
|
return result;
|
||||||
|
@ -81,7 +83,7 @@ QString InputConfiguration::configurationLayout(QString pluginName) {
|
||||||
|
|
||||||
void InputConfiguration::setConfigurationSettings(QJsonObject configurationSettings, QString pluginName) {
|
void InputConfiguration::setConfigurationSettings(QJsonObject configurationSettings, QString pluginName) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "setConfigurationSettings", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "setConfigurationSettings",
|
||||||
Q_ARG(QJsonObject, configurationSettings),
|
Q_ARG(QJsonObject, configurationSettings),
|
||||||
Q_ARG(QString, pluginName));
|
Q_ARG(QString, pluginName));
|
||||||
return;
|
return;
|
||||||
|
@ -97,7 +99,7 @@ void InputConfiguration::setConfigurationSettings(QJsonObject configurationSetti
|
||||||
QJsonObject InputConfiguration::configurationSettings(QString pluginName) {
|
QJsonObject InputConfiguration::configurationSettings(QString pluginName) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QJsonObject result;
|
QJsonObject result;
|
||||||
QMetaObject::invokeMethod(this, "configurationSettings", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "configurationSettings",
|
||||||
Q_RETURN_ARG(QJsonObject, result),
|
Q_RETURN_ARG(QJsonObject, result),
|
||||||
Q_ARG(QString, pluginName));
|
Q_ARG(QString, pluginName));
|
||||||
return result;
|
return result;
|
||||||
|
@ -113,7 +115,7 @@ QJsonObject InputConfiguration::configurationSettings(QString pluginName) {
|
||||||
|
|
||||||
void InputConfiguration::calibratePlugin(QString pluginName) {
|
void InputConfiguration::calibratePlugin(QString pluginName) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "calibratePlugin", Qt::BlockingQueuedConnection);
|
BLOCKING_INVOKE_METHOD(this, "calibratePlugin");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ void InputConfiguration::calibratePlugin(QString pluginName) {
|
||||||
bool InputConfiguration::uncalibratePlugin(QString pluginName) {
|
bool InputConfiguration::uncalibratePlugin(QString pluginName) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
bool result;
|
bool result;
|
||||||
QMetaObject::invokeMethod(this, "uncalibratePlugin", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "uncalibratePlugin",
|
||||||
Q_ARG(bool, result));
|
Q_ARG(bool, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
#include "ClipCache.h"
|
#include "ClipCache.h"
|
||||||
#include "impl/PointerClip.h"
|
#include "impl/PointerClip.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
@ -37,7 +39,7 @@ ClipCache::ClipCache(QObject* parent) :
|
||||||
NetworkClipLoaderPointer ClipCache::getClipLoader(const QUrl& url) {
|
NetworkClipLoaderPointer ClipCache::getClipLoader(const QUrl& url) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
NetworkClipLoaderPointer result;
|
NetworkClipLoaderPointer result;
|
||||||
QMetaObject::invokeMethod(this, "getClipLoader", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(this, "getClipLoader",
|
||||||
Q_RETURN_ARG(NetworkClipLoaderPointer, result), Q_ARG(const QUrl&, url));
|
Q_RETURN_ARG(NetworkClipLoaderPointer, result), Q_ARG(const QUrl&, url));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ void DeferredFrameTransform::update(RenderArgs* args) {
|
||||||
args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono);
|
args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono);
|
||||||
|
|
||||||
// Running in stero ?
|
// Running in stero ?
|
||||||
bool isStereo = args->_context->isStereo();
|
bool isStereo = args->isStereo();
|
||||||
if (!isStereo) {
|
if (!isStereo) {
|
||||||
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono;
|
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono;
|
||||||
frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
|
frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
#include <glm/gtx/norm.hpp>
|
#include <glm/gtx/norm.hpp>
|
||||||
|
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
#include <GeometryUtil.h>
|
#include <GeometryUtil.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
@ -870,7 +871,7 @@ bool Model::getRelativeDefaultJointTranslation(int jointIndex, glm::vec3& transl
|
||||||
QStringList Model::getJointNames() const {
|
QStringList Model::getJointNames() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
QMetaObject::invokeMethod(const_cast<Model*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
BLOCKING_INVOKE_METHOD(const_cast<Model*>(this), "getJointNames",
|
||||||
Q_RETURN_ARG(QStringList, result));
|
Q_RETURN_ARG(QStringList, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,7 +406,7 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
|
||||||
batch.setFramebuffer(blitFbo);
|
batch.setFramebuffer(blitFbo);
|
||||||
|
|
||||||
if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||||
if (renderArgs->_context->isStereo()) {
|
if (renderArgs->isStereo()) {
|
||||||
gpu::Vec4i srcRectLeft;
|
gpu::Vec4i srcRectLeft;
|
||||||
srcRectLeft.z = width / 2;
|
srcRectLeft.z = width / 2;
|
||||||
srcRectLeft.w = height;
|
srcRectLeft.w = height;
|
||||||
|
|
|
@ -459,7 +459,7 @@ void SurfaceGeometryPass::run(const render::RenderContextPointer& renderContext,
|
||||||
auto diffuseVPipeline = _diffusePass.getBlurVPipeline();
|
auto diffuseVPipeline = _diffusePass.getBlurVPipeline();
|
||||||
auto diffuseHPipeline = _diffusePass.getBlurHPipeline();
|
auto diffuseHPipeline = _diffusePass.getBlurHPipeline();
|
||||||
|
|
||||||
_diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->_context->isStereo());
|
_diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->isStereo());
|
||||||
glm::ivec2 textureSize(curvatureTexture->getDimensions());
|
glm::ivec2 textureSize(curvatureTexture->getDimensions());
|
||||||
_diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport));
|
_diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport));
|
||||||
_diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]);
|
_diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]);
|
||||||
|
|
|
@ -34,6 +34,8 @@ in vec2 _texCoord0;
|
||||||
out vec4 _fragColor;
|
out vec4 _fragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
_fragColor = vec4(0.0);
|
||||||
|
|
||||||
// Grab the fragment data from the uv
|
// Grab the fragment data from the uv
|
||||||
vec2 texCoord = _texCoord0.st;
|
vec2 texCoord = _texCoord0.st;
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,8 @@ namespace render {
|
||||||
void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); }
|
void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); }
|
||||||
void popViewFrustum() { _viewFrustums.pop(); }
|
void popViewFrustum() { _viewFrustums.pop(); }
|
||||||
|
|
||||||
|
bool isStereo() const { return _displayMode != MONO; }
|
||||||
|
|
||||||
std::shared_ptr<gpu::Context> _context;
|
std::shared_ptr<gpu::Context> _context;
|
||||||
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer;
|
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer;
|
||||||
std::shared_ptr<render::ShapePipeline> _pipeline;
|
std::shared_ptr<render::ShapePipeline> _pipeline;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue