mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 05:33:55 +02:00
Merge branch 'master' into bug/5950
This commit is contained in:
commit
d5c88bc6de
178 changed files with 5247 additions and 2289 deletions
assignment-client/src
cmake
domain-server
gvr-interface/src
interface
external/leapmotion
resources
controllers
qml/hifi
src
Application.cppApplication.hAvatarBookmarks.cppAvatarBookmarks.hBookmarks.cppBookmarks.hLocationBookmarks.cppLocationBookmarks.hMenu.cppMenu.hSecondaryCamera.cpp
avatar
devices
main.cppscripting
Audio.cppAudio.hAudioDevices.cppAudioDevices.hClipboardScriptingInterface.cppClipboardScriptingInterface.hControllerScriptingInterface.cppControllerScriptingInterface.hHMDScriptingInterface.cppHMDScriptingInterface.hMenuScriptingInterface.cppTestScriptingInterface.cppWindowScriptingInterface.cppWindowScriptingInterface.h
ui
libraries
animation/src
audio-client/src
audio/src
avatars-renderer/src/avatars-renderer
avatars/src
controllers/src/controllers
display-plugins/src/display-plugins
entities-renderer/src
entities/src
gpu-gl/src/gpu/gl
gpu/src/gpu
model-networking/src/model-networking
networking/src
plugins/src/plugins
recording/src/recording
render-utils/src
DeferredFrameTransform.cppModel.cppRenderDeferredTask.cppSurfaceGeometryPass.cpplocal_lights_shading.slf
render/src/render
|
@ -16,6 +16,7 @@
|
|||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <Assignment.h>
|
||||
|
@ -141,7 +142,7 @@ void AssignmentClient::stopAssignmentClient() {
|
|||
QThread* currentAssignmentThread = _currentAssignment->thread();
|
||||
|
||||
// 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
|
||||
_currentAssignment->deleteLater();
|
||||
|
|
|
@ -9,8 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QThread>
|
||||
#include "AssignmentClientApp.h"
|
||||
|
||||
#include <QtCore/QCommandLineParser>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <LogHandler.h>
|
||||
#include <SharedUtil.h>
|
||||
|
@ -20,10 +24,6 @@
|
|||
#include "Assignment.h"
|
||||
#include "AssignmentClient.h"
|
||||
#include "AssignmentClientMonitor.h"
|
||||
#include "AssignmentClientApp.h"
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStandardPaths>
|
||||
|
||||
|
||||
AssignmentClientApp::AssignmentClientApp(int argc, char* 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");
|
||||
parser.addOption(logDirectoryOption);
|
||||
|
||||
const QCommandLineOption parentPIDOption(PARENT_PID_OPTION, "PID of the parent process", "parent-pid");
|
||||
parser.addOption(parentPIDOption);
|
||||
|
||||
if (!parser.parse(QCoreApplication::arguments())) {
|
||||
qCritical() << parser.errorText() << endl;
|
||||
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");
|
||||
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
|
|
|
@ -131,7 +131,6 @@ void AssignmentClientMonitor::aboutToQuit() {
|
|||
void AssignmentClientMonitor::spawnChildClient() {
|
||||
QProcess* assignmentClient = new QProcess(this);
|
||||
|
||||
|
||||
// unparse the parts of the command-line that the child cares about
|
||||
QStringList _childArguments;
|
||||
if (_assignmentPool != "") {
|
||||
|
@ -160,6 +159,9 @@ void AssignmentClientMonitor::spawnChildClient() {
|
|||
_childArguments.append("--" + ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION);
|
||||
_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;
|
||||
|
||||
|
||||
|
|
|
@ -285,6 +285,13 @@ void AvatarMixer::start() {
|
|||
// is guaranteed to not be accessed by other thread
|
||||
void AvatarMixer::manageIdentityData(const SharedNodePointer& node) {
|
||||
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;
|
||||
if (nodeData && nodeData->getAvatarSessionDisplayNameMustChange()) {
|
||||
AvatarData& avatar = nodeData->getAvatar();
|
||||
|
|
|
@ -320,14 +320,18 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
|||
++numOtherAvatars;
|
||||
|
||||
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
|
||||
// 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);
|
||||
|
||||
// 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();
|
||||
|
||||
// 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
|
||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
||||
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 <glm/gtx/transform.hpp>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <AnimUtil.h>
|
||||
#include "ScriptableAvatar.h"
|
||||
|
@ -49,7 +50,7 @@ void ScriptableAvatar::stopAnimation() {
|
|||
AnimationDetails ScriptableAvatar::getAnimationDetails() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AnimationDetails result;
|
||||
QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "getAnimationDetails",
|
||||
Q_RETURN_ARG(AnimationDetails, 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()
|
||||
|
||||
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)
|
||||
endif()
|
||||
|
||||
if (MSVC11)
|
||||
elseif (MSVC_VERSION EQUAL 1700)
|
||||
set(VS_PREFIX vs2012)
|
||||
endif()
|
||||
|
||||
if (MSVC10)
|
||||
elseif (MSVC_VERSION EQUAL 1600)
|
||||
set(VS_PREFIX vs2010)
|
||||
endif()
|
||||
|
||||
if (MSVC90)
|
||||
elseif (MSVC_VERSION EQUAL 1500)
|
||||
set(VS_PREFIX vs2008)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
{
|
||||
"name": "descriptors",
|
||||
"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.",
|
||||
"settings": [
|
||||
{
|
||||
|
|
|
@ -162,8 +162,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
|
||||
_gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request
|
||||
|
||||
//send signal to DomainMetadata when descriptors changed
|
||||
_metadata = new DomainMetadata(this);
|
||||
|
||||
connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated,
|
||||
_metadata, &DomainMetadata::descriptorsChanged);
|
||||
|
||||
qDebug() << "domain-server is running";
|
||||
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");
|
||||
parser.addOption(masterConfigOption);
|
||||
|
||||
const QCommandLineOption parentPIDOption(PARENT_PID_OPTION, "PID of the parent process", "parent-pid");
|
||||
parser.addOption(parentPIDOption);
|
||||
|
||||
if (!parser.parse(QCoreApplication::arguments())) {
|
||||
qWarning() << parser.errorText() << endl;
|
||||
|
@ -249,6 +253,17 @@ void DomainServer::parseCommandLine() {
|
|||
_overrideDomainID = true;
|
||||
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() {
|
||||
|
|
|
@ -1198,7 +1198,8 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
|
|||
static const QString SECURITY_ROOT_KEY = "security";
|
||||
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
|
||||
static const QString BROADCASTING_KEY = "broadcasting";
|
||||
|
||||
static const QString DESCRIPTION_ROOT_KEY = "descriptors";
|
||||
|
||||
auto& settingsVariant = _configMap.getConfig();
|
||||
bool needRestart = false;
|
||||
|
||||
|
@ -1265,7 +1266,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
|
|||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
const QJsonValue& settingValue = rootValue.toObject()[settingKey];
|
||||
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) {
|
||||
needRestart = true;
|
||||
}
|
||||
|
|
|
@ -63,10 +63,7 @@ void RenderingClient::sendAvatarPacket() {
|
|||
}
|
||||
|
||||
void RenderingClient::cleanupBeforeQuit() {
|
||||
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"stop", Qt::BlockingQueuedConnection);
|
||||
|
||||
DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
|
||||
// destroy the AudioClient so it and its thread will safely go down
|
||||
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.
|
||||
This readme.txt should be there as well.
|
||||
|
||||
The files neeeded in the folders are:
|
||||
The files needed in the folders are:
|
||||
|
||||
include/
|
||||
- Leap.h
|
||||
|
@ -21,8 +21,8 @@ Interface has been tested with SDK versions:
|
|||
x86/
|
||||
- Leap.dll
|
||||
- Leap.lib
|
||||
- mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
|
||||
- mscvcr120.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 redistributable installed)
|
||||
- lipLeap.dylib
|
||||
libc++/
|
||||
-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).
|
||||
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.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.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.RightFoot", "to": "Actions.RightFoot" },
|
||||
|
|
|
@ -34,36 +34,32 @@
|
|||
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
||||
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
||||
|
||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand", "when": [ "Application.InHMD" ] },
|
||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand", "when": [ "Application.InHMD" ] },
|
||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
|
||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
|
||||
|
||||
{
|
||||
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}],
|
||||
"when": [ "Application.InHMD" ]
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
|
||||
},
|
||||
|
||||
{
|
||||
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}],
|
||||
"when": [ "Application.InHMD" ]
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
|
||||
},
|
||||
|
||||
{
|
||||
"from": "Vive.Hips", "to" : "Standard.Hips",
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}],
|
||||
"when": [ "Application.InHMD" ]
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
|
||||
},
|
||||
|
||||
{
|
||||
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}],
|
||||
"when": [ "Application.InHMD" ]
|
||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
|
||||
},
|
||||
|
||||
{ "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.LeftArm", "to" : "Standard.LeftArm", "when": [ "Application.InHMD" ] }
|
||||
{ "from": "Vive.RightArm", "to" : "Standard.RightArm"},
|
||||
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ PreferencesDialog {
|
|||
id: root
|
||||
objectName: "GeneralPreferencesDialog"
|
||||
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 {
|
||||
category: root.objectName
|
||||
property alias x: root.x
|
||||
|
|
|
@ -25,11 +25,12 @@ Rectangle {
|
|||
signal canceled()
|
||||
signal restart()
|
||||
|
||||
property int count: 3
|
||||
property int count: 5
|
||||
property string calibratingText: "CALIBRATING..."
|
||||
property string calibratingCountText: "CALIBRATION STARTING IN"
|
||||
property string calibrationSuccess: "CALIBRATION COMPLETED"
|
||||
property string calibrationFailed: "CALIBRATION FAILED"
|
||||
property string instructionText: "Please stand in a T-Pose during calibration"
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
visible: true
|
||||
|
@ -158,6 +159,15 @@ Rectangle {
|
|||
|
||||
onClicked: {
|
||||
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();
|
||||
info.count = (timer.interval / 1000);
|
||||
numberAnimation.start();
|
||||
|
@ -178,6 +188,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function start(interval, countNumber) {
|
||||
countDown.visible = true;
|
||||
statusText.color = hifi.colors.blueHighlight;
|
||||
|
@ -201,6 +212,7 @@ Rectangle {
|
|||
busyIndicator.running = false;
|
||||
statusText.text = info.calibrationSuccess
|
||||
statusText.color = hifi.colors.greenHighlight
|
||||
directions.text = "SUCCESS"
|
||||
closeWindow.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -458,7 +458,7 @@ Rectangle {
|
|||
width: glyphButton.width + calibrationText.width + padding
|
||||
height: hifi.dimensions.controlLineHeight
|
||||
anchors.top: bottomSeperator.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.topMargin: 15
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: leftMargin
|
||||
|
||||
|
@ -590,16 +590,24 @@ Rectangle {
|
|||
lastConfiguration = composeConfigurationSettings();
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
var settings = InputConfiguration.configurationSettings(pluginName);
|
||||
var data = {
|
||||
"num_pucks": settings["puckCount"]
|
||||
}
|
||||
UserActivityLogger.logAction("mocap_ui_close_dialog", data);
|
||||
}
|
||||
|
||||
HifiControls.SpinBox {
|
||||
id: timeToCalibrate
|
||||
width: 70
|
||||
anchors.top: calibrationButton.bottom
|
||||
anchors.topMargin: 40
|
||||
anchors.topMargin: 20
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: leftMargin
|
||||
|
||||
minimumValue: 3
|
||||
value: 3
|
||||
minimumValue: 5
|
||||
value: 5
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
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 {
|
||||
id: numberAnimation
|
||||
target: openVrConfiguration
|
||||
|
@ -641,17 +700,39 @@ Rectangle {
|
|||
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) {
|
||||
var calibrationScreen = stack.currentItem;
|
||||
|
||||
if (!status["UI"]) {
|
||||
calibratingScreen = screen.createObject();
|
||||
stack.push(calibratingScreen);
|
||||
}
|
||||
|
||||
if (status["calibrated"]) {
|
||||
calibrationScreen.success();
|
||||
|
||||
if (status["UI"]) {
|
||||
logAction("mocap_ui_success", status);
|
||||
}
|
||||
|
||||
} else if (!status["calibrated"]) {
|
||||
var uncalibrated = status["success"];
|
||||
if (!uncalibrated) {
|
||||
calibrationScreen.failure();
|
||||
calibrationScreen.failure();
|
||||
|
||||
if (status["UI"]) {
|
||||
logAction("mocap_ui_failed", status);
|
||||
}
|
||||
}
|
||||
|
||||
updateCalibrationButton();
|
||||
}
|
||||
|
||||
|
@ -698,6 +779,7 @@ Rectangle {
|
|||
|
||||
var HmdHead = settings["HMDHead"];
|
||||
var viveController = settings["handController"];
|
||||
var desktopMode = settings["desktopMode"];
|
||||
|
||||
if (HmdHead) {
|
||||
headBox.checked = true;
|
||||
|
@ -715,8 +797,16 @@ Rectangle {
|
|||
handBox.checked = false;
|
||||
}
|
||||
|
||||
viveInDesktop.checked = desktopMode;
|
||||
|
||||
initializeButtonState();
|
||||
updateCalibrationText();
|
||||
|
||||
var data = {
|
||||
"num_pucks": settings["puckCount"]
|
||||
};
|
||||
|
||||
UserActivityLogger.logAction("mocap_ui_open_dialog", data);
|
||||
}
|
||||
|
||||
function displayTrackerConfiguration(type) {
|
||||
|
@ -865,7 +955,8 @@ Rectangle {
|
|||
var settingsObject = {
|
||||
"bodyConfiguration": trackerConfiguration,
|
||||
"headConfiguration": headObject,
|
||||
"handConfiguration": handObject
|
||||
"handConfiguration": handObject,
|
||||
"desktopMode": viveInDesktop.checked
|
||||
}
|
||||
|
||||
return settingsObject;
|
||||
|
|
|
@ -94,10 +94,20 @@ StackView {
|
|||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: true
|
||||
onPressed: {
|
||||
parent.forceActiveFocus();
|
||||
addressBarDialog.keyboardEnabled = false;
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
|
@ -227,9 +237,9 @@ StackView {
|
|||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onClicked: {
|
||||
if (!addressLine.focus || !HMD.active) {
|
||||
addressLine.focus = true;
|
||||
addressLine.forceActiveFocus();
|
||||
addressLine.focus = true;
|
||||
addressLine.forceActiveFocus();
|
||||
if (HMD.active) {
|
||||
addressBarDialog.keyboardEnabled = HMD.active;
|
||||
}
|
||||
tabletRoot.playButtonClickSound();
|
||||
|
|
|
@ -32,6 +32,6 @@ StackView {
|
|||
TabletPreferencesDialog {
|
||||
id: root
|
||||
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/QMimeData>
|
||||
#include <QtCore/QThreadPool>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtGui/QWindow>
|
||||
|
@ -48,6 +49,7 @@
|
|||
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <StatTracker.h>
|
||||
#include <Trace.h>
|
||||
|
@ -145,7 +147,6 @@
|
|||
#include "avatar/MyHead.h"
|
||||
#include "CrashHandler.h"
|
||||
#include "devices/DdeFaceTracker.h"
|
||||
#include "devices/Leapmotion.h"
|
||||
#include "DiscoverabilityManager.h"
|
||||
#include "GLCanvas.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";
|
||||
bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
|
||||
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();
|
||||
|
||||
|
@ -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
|
||||
updateHeartbeat();
|
||||
|
||||
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
||||
connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
||||
connect(&_settingsThread, SIGNAL(started()), &_settingsTimer, SLOT(start()));
|
||||
connect(&_settingsThread, SIGNAL(finished()), &_settingsTimer, SLOT(stop()));
|
||||
_settingsTimer.moveToThread(&_settingsThread);
|
||||
_settingsTimer.setSingleShot(false);
|
||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
|
||||
_settingsThread.setPriority(QThread::LowestPriority);
|
||||
_settingsThread.start();
|
||||
|
||||
QTimer* settingsTimer = new QTimer();
|
||||
moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{
|
||||
connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{
|
||||
// Disconnect the signal from the save settings
|
||||
QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
||||
// Stop the settings timer
|
||||
settingsTimer->stop();
|
||||
// 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)) {
|
||||
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()) {
|
||||
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;
|
||||
}
|
||||
|
@ -1802,11 +1820,13 @@ void Application::cleanupBeforeQuit() {
|
|||
locationUpdateTimer.stop();
|
||||
identityPacketTimer.stop();
|
||||
pingTimer.stop();
|
||||
QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
|
||||
|
||||
// save state
|
||||
_settingsThread.quit();
|
||||
saveSettings();
|
||||
// Wait for the settings thread to shut down, and save the settings one last time when it's safe
|
||||
if (_settingsGuard.wait()) {
|
||||
// save state
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
_window->saveGeometry();
|
||||
|
||||
// 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,
|
||||
// so it must be explicitly synchronously stopped here
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"cleanupBeforeQuit", Qt::BlockingQueuedConnection);
|
||||
DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
|
||||
|
||||
// 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
|
||||
|
@ -1886,8 +1905,6 @@ Application::~Application() {
|
|||
// remove the NodeList from the DependencyManager
|
||||
DependencyManager::destroy<NodeList>();
|
||||
|
||||
Leapmotion::destroy();
|
||||
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
steamClient->shutdown();
|
||||
}
|
||||
|
@ -2154,48 +2171,74 @@ void Application::paintGL() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto displayPlugin = getActiveDisplayPlugin();
|
||||
// FIXME not needed anymore?
|
||||
_offscreenContext->makeCurrent();
|
||||
DisplayPluginPointer displayPlugin;
|
||||
{
|
||||
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
|
||||
if (!displayPlugin->beginFrameRender(_frameCount)) {
|
||||
_inPaint = false;
|
||||
updateDisplayMode();
|
||||
return;
|
||||
{
|
||||
PROFILE_RANGE(render, "/offscreenMakeCurrent");
|
||||
// FIXME not needed anymore?
|
||||
_offscreenContext->makeCurrent();
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||
{
|
||||
PROFILE_RANGE(render, "/updateAvatar");
|
||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||
}
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
||||
RenderArgs renderArgs;
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.calculate();
|
||||
}
|
||||
RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
renderArgs.setViewFrustum(_viewFrustum);
|
||||
PROFILE_RANGE(render, "/buildFrustrumAndArgs");
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_viewFrustum.calculate();
|
||||
}
|
||||
renderArgs = RenderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
renderArgs.setViewFrustum(_viewFrustum);
|
||||
}
|
||||
}
|
||||
|
||||
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||
resizeGL();
|
||||
|
||||
_gpuContext->beginFrame(getHMDSensorPose());
|
||||
// Reset the gpu::Context Stages
|
||||
// Back to the default framebuffer;
|
||||
gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
|
||||
batch.resetStages();
|
||||
});
|
||||
{
|
||||
PROFILE_RANGE(render, "/resizeGL");
|
||||
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||
resizeGL();
|
||||
}
|
||||
|
||||
{
|
||||
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");
|
||||
// NOTE: There is no batch associated with this renderArgs
|
||||
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
|
||||
|
@ -2206,114 +2249,127 @@ void Application::paintGL() {
|
|||
|
||||
glm::vec3 boomOffset;
|
||||
{
|
||||
PerformanceTimer perfTimer("CameraUpdates");
|
||||
PROFILE_RANGE(render, "/updateCamera");
|
||||
{
|
||||
PerformanceTimer perfTimer("CameraUpdates");
|
||||
|
||||
auto myAvatar = getMyAvatar();
|
||||
boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
|
||||
auto myAvatar = getMyAvatar();
|
||||
boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
|
||||
|
||||
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::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
||||
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());
|
||||
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::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
|
||||
cameraMenuChanged();
|
||||
}
|
||||
} 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);
|
||||
// The render mode is default or mirror if the camera is in mirror mode, assigned further below
|
||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
|
||||
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) {
|
||||
// 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()) {
|
||||
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
||||
_myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
|
||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||
_myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
|
||||
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
_myCamera.setPosition(extractTranslation(camMat));
|
||||
_myCamera.setOrientation(glm::quat_cast(camMat));
|
||||
} else {
|
||||
_myCamera.setOrientation(cameraEntity->getRotation());
|
||||
_myCamera.setPosition(cameraEntity->getPosition());
|
||||
_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());
|
||||
// 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
|
||||
if (!isHMDMode()) {
|
||||
_myCamera.update(1.0f / _frameCounter.rate());
|
||||
// Update camera position
|
||||
if (!isHMDMode()) {
|
||||
_myCamera.update(1.0f / _frameCounter.rate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());
|
||||
{
|
||||
PROFILE_RANGE(render, "/updateCompositor");
|
||||
getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());
|
||||
}
|
||||
|
||||
// Primary rendering pass
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
const QSize size = framebufferCache->getFrameBufferSize();
|
||||
// Final framebuffer that will be handled to the display-plugin
|
||||
auto finalFramebuffer = framebufferCache->getFramebuffer();
|
||||
gpu::FramebufferPointer finalFramebuffer;
|
||||
QSize finalFramebufferSize;
|
||||
{
|
||||
PROFILE_RANGE(render, "/getOutputFramebuffer");
|
||||
// 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");
|
||||
PerformanceTimer perfTimer("mainRender");
|
||||
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
|
||||
renderArgs._viewport = ivec4(0, 0, size.width(), size.height());
|
||||
renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height());
|
||||
if (displayPlugin->isStereo()) {
|
||||
// Stereo modes will typically have a larger projection matrix overall,
|
||||
// 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 <pdh.h>
|
||||
#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 int numProcessors;
|
||||
|
@ -3665,6 +3848,26 @@ void getCpuUsage(vec3& systemAndUser) {
|
|||
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
|
||||
|
||||
|
||||
|
@ -3685,15 +3888,17 @@ void Application::idle(float nsecsElapsed) {
|
|||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// If tracing is enabled then monitor the CPU in a separate thread
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
initCpuUsage();
|
||||
std::call_once(once, [&] {
|
||||
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
|
||||
|
||||
|
||||
|
@ -4055,8 +4260,6 @@ void Application::init() {
|
|||
|
||||
qCDebug(interfaceapp) << "Loaded settings";
|
||||
|
||||
Leapmotion::init();
|
||||
|
||||
// fire off an immediate domain-server check in now that settings are loaded
|
||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||
|
||||
|
@ -4520,7 +4723,6 @@ void Application::update(float deltaTime) {
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("devices");
|
||||
DeviceTracker::updateAll();
|
||||
|
||||
FaceTracker* tracker = getSelectedFaceTracker();
|
||||
if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) {
|
||||
|
@ -4589,8 +4791,6 @@ void Application::update(float deltaTime) {
|
|||
keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData);
|
||||
}
|
||||
|
||||
_controllerScriptingInterface->updateInputControllers();
|
||||
|
||||
// Transfer the user inputs to the driveKeys
|
||||
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
||||
myAvatar->clearDriveKeys();
|
||||
|
@ -4615,6 +4815,31 @@ void Application::update(float deltaTime) {
|
|||
auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;
|
||||
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 rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT);
|
||||
myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix));
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QUndoStack>
|
||||
|
||||
#include <ThreadHelpers.h>
|
||||
#include <AbstractScriptingServicesInterface.h>
|
||||
#include <AbstractViewStateInterface.h>
|
||||
#include <EntityEditPacketSender.h>
|
||||
|
@ -298,7 +299,6 @@ public:
|
|||
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
||||
QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; }
|
||||
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
||||
void setCacheOverrideDir(const QString& dirName) { _cacheDir = dirName; }
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
@ -596,8 +596,7 @@ private:
|
|||
|
||||
bool _notifiedPacketVersionMismatchThisDomain;
|
||||
|
||||
QThread _settingsThread;
|
||||
QTimer _settingsTimer;
|
||||
ConditionalGuard _settingsGuard;
|
||||
|
||||
GLCanvas* _glWidget{ nullptr };
|
||||
|
||||
|
@ -691,6 +690,5 @@ private:
|
|||
QUrl _avatarOverrideUrl;
|
||||
bool _saveAvatarOverrideUrl { false };
|
||||
|
||||
QString _cacheDir;
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
#include <QQmlContext>
|
||||
#include <QList>
|
||||
|
||||
#include <Application.h>
|
||||
#include <OffscreenUi.h>
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include "AvatarBookmarks.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "QVariantGLM.h"
|
||||
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
||||
AvatarBookmarks::AvatarBookmarks() {
|
||||
|
@ -58,16 +61,48 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
|||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarBookmark);
|
||||
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);
|
||||
}
|
||||
|
||||
void AvatarBookmarks::changeToBookmarkedAvatar() {
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
const QString& address = action->data().toString();
|
||||
|
||||
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() {
|
||||
|
@ -83,13 +118,23 @@ void AvatarBookmarks::addBookmark() {
|
|||
}
|
||||
|
||||
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();
|
||||
changeAction->setData(address);
|
||||
changeAction->setData(bookmark);
|
||||
connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar()));
|
||||
if (!_isMenuSorted) {
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
||||
|
|
|
@ -21,18 +21,23 @@ class AvatarBookmarks: public Bookmarks, public Dependency {
|
|||
|
||||
public:
|
||||
AvatarBookmarks();
|
||||
|
||||
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
||||
|
||||
public slots:
|
||||
void addBookmark();
|
||||
|
||||
protected:
|
||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
|
||||
void readFromFile();
|
||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) override;
|
||||
void readFromFile() override;
|
||||
|
||||
private:
|
||||
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:
|
||||
void changeToBookmarkedAvatar();
|
||||
|
|
|
@ -28,19 +28,6 @@ Bookmarks::Bookmarks() :
|
|||
_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() {
|
||||
QStringList bookmarkList;
|
||||
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();
|
||||
if (contains(bookmarkName)) {
|
||||
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.",
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
|
||||
|
||||
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
|
||||
if (result != QMessageBox::Yes) {
|
||||
return;
|
||||
|
@ -83,19 +69,20 @@ void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bo
|
|||
removeBookmarkFromMenu(menubar, bookmarkName);
|
||||
}
|
||||
|
||||
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
||||
addBookmarkToMenu(menubar, bookmarkName, bookmark);
|
||||
insert(bookmarkName, bookmark); // Overwrites any item with the same bookmarkName.
|
||||
enableMenuItems(true);
|
||||
}
|
||||
|
||||
void Bookmarks::insert(const QString& name, const QString& address) {
|
||||
_bookmarks.insert(name, address);
|
||||
void Bookmarks::insert(const QString& name, const QVariant& bookmark) {
|
||||
_bookmarks.insert(name, bookmark);
|
||||
|
||||
if (contains(name)) {
|
||||
qCDebug(interfaceapp) << "Added bookmark:" << name << "," << address;
|
||||
qCDebug(interfaceapp) << "Added bookmark:" << name;
|
||||
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:
|
||||
Bookmarks();
|
||||
|
||||
virtual void setupMenus(Menu* menubar, MenuWrapper* menu);
|
||||
virtual void setupMenus(Menu* menubar, MenuWrapper* menu) = 0;
|
||||
QString addressForBookmark(const QString& name) const;
|
||||
|
||||
protected:
|
||||
virtual void addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress);
|
||||
virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0;
|
||||
void addBookmarkToFile(const QString& bookmarkName, const QVariant& bookmark);
|
||||
virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) = 0;
|
||||
void enableMenuItems(bool enabled);
|
||||
void readFromFile();
|
||||
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
|
||||
virtual void readFromFile();
|
||||
void insert(const QString& name, const QVariant& address); // Overwrites any existing entry with same name.
|
||||
void sortActions(Menu* menubar, MenuWrapper* menu);
|
||||
int getMenuItemLocation(QList<QAction*> actions, const QString& name) const;
|
||||
|
||||
|
||||
bool contains(const QString& name) const;
|
||||
|
||||
QVariantMap _bookmarks; // { name: url, ... }
|
||||
QPointer<MenuWrapper> _bookmarksMenu;
|
||||
QPointer<QAction> _deleteBookmarksAction;
|
||||
|
@ -50,7 +52,6 @@ protected slots:
|
|||
|
||||
private:
|
||||
void remove(const QString& name);
|
||||
bool contains(const QString& name) const;
|
||||
static bool sortOrder(QAction* a, QAction* b);
|
||||
|
||||
void persistToFile();
|
||||
|
|
|
@ -41,13 +41,25 @@ void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
|||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
|
||||
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);
|
||||
}
|
||||
|
||||
void LocationBookmarks::setHomeLocation() {
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||
|
||||
Bookmarks::addBookmarkToFile(HOME_BOOKMARK, bookmarkAddress);
|
||||
}
|
||||
|
||||
|
@ -74,7 +86,7 @@ void LocationBookmarks::addBookmark() {
|
|||
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();
|
||||
teleportAction->setData(address);
|
||||
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);
|
||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ public slots:
|
|||
void addBookmark();
|
||||
|
||||
protected:
|
||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
|
||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& address) override;
|
||||
|
||||
private:
|
||||
const QString LOCATIONBOOKMARKS_FILENAME = "bookmarks.json";
|
||||
|
|
|
@ -566,9 +566,6 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
|
||||
avatar.get(), SLOT(setEnableDebugDrawHandControllers(bool)));
|
||||
|
||||
MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion");
|
||||
addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false);
|
||||
|
||||
// Developer > Entities >>>
|
||||
MenuWrapper* entitiesOptionsMenu = developerMenu->addMenu("Entities");
|
||||
|
||||
|
|
|
@ -114,7 +114,6 @@ namespace MenuOption {
|
|||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IndependentMode = "Independent Mode";
|
||||
const QString ActionMotorControl = "Enable Default Motor Control";
|
||||
const QString LeapMotionOnHMD = "Leap Motion on HMD";
|
||||
const QString LoadScript = "Open and Run Script File...";
|
||||
const QString LoadScriptURL = "Open and Run Script from URL...";
|
||||
const QString LodTools = "LOD Tools";
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.disableContextStereo();
|
||||
batch.disableContextViewCorrection();
|
||||
});
|
||||
|
||||
auto srcViewFrustum = args->getViewFrustum();
|
||||
|
@ -112,6 +113,7 @@ public:
|
|||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.restoreContextStereo();
|
||||
batch.restoreContextViewCorrection();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#endif
|
||||
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <AvatarData.h>
|
||||
#include <PerfStat.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
@ -482,7 +483,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay&
|
|||
const QScriptValue& avatarIdsToDiscard) {
|
||||
RayToAvatarIntersectionResult result;
|
||||
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_ARG(const PickRay&, ray),
|
||||
Q_ARG(const QScriptValue&, avatarIdsToInclude),
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <scripting/HMDScriptingInterface.h>
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
|
@ -897,7 +898,7 @@ void MyAvatar::restoreAnimation() {
|
|||
QStringList MyAvatar::getAnimationRoles() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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 _skeletonModel->getRig().getAnimationRoles();
|
||||
|
@ -1368,7 +1369,7 @@ void MyAvatar::resetFullAvatarURL() {
|
|||
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "useFullAvatarURL",
|
||||
Q_ARG(const QUrl&, fullAvatarURL),
|
||||
Q_ARG(const QString&, modelName));
|
||||
return;
|
||||
|
@ -1394,7 +1395,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
|
|||
|
||||
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAttachmentData", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||
return;
|
||||
}
|
||||
|
@ -1455,6 +1456,19 @@ controller::Pose MyAvatar::getRightHandControllerPoseInAvatarFrame() const {
|
|||
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) {
|
||||
_leftFootControllerPoseInSensorFrameCache.set(left);
|
||||
_rightFootControllerPoseInSensorFrameCache.set(right);
|
||||
|
@ -1620,7 +1634,8 @@ void MyAvatar::prepareForPhysicsSimulation() {
|
|||
_characterController.setParentVelocity(parentVelocity);
|
||||
|
||||
_characterController.setPositionAndOrientation(getPosition(), getOrientation());
|
||||
if (qApp->isHMDMode()) {
|
||||
auto headPose = getHeadControllerPoseInAvatarFrame();
|
||||
if (headPose.isValid()) {
|
||||
_follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix, hasDriveInput());
|
||||
} else {
|
||||
_follow.deactivate();
|
||||
|
@ -2358,7 +2373,7 @@ bool MyAvatar::safeLanding(const glm::vec3& position) {
|
|||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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;
|
||||
}
|
||||
glm::vec3 better;
|
||||
|
@ -2524,6 +2539,21 @@ bool MyAvatar::getFlyingEnabled() {
|
|||
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) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
|
|
|
@ -366,7 +366,7 @@ public:
|
|||
float getDriveKey(DriveKeys key) const;
|
||||
Q_INVOKABLE float getRawDriveKey(DriveKeys key) const;
|
||||
void relayDriveKeysToCharacterController();
|
||||
|
||||
|
||||
Q_INVOKABLE void disableDriveKey(DriveKeys key);
|
||||
Q_INVOKABLE void enableDriveKey(DriveKeys key);
|
||||
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;
|
||||
|
@ -474,6 +474,11 @@ public:
|
|||
controller::Pose getLeftHandControllerPoseInAvatarFrame() 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);
|
||||
controller::Pose getLeftFootControllerPoseInSensorFrame() const;
|
||||
controller::Pose getRightFootControllerPoseInSensorFrame() const;
|
||||
|
@ -512,6 +517,9 @@ public:
|
|||
Q_INVOKABLE void setFlyingEnabled(bool enabled);
|
||||
Q_INVOKABLE bool getFlyingEnabled();
|
||||
|
||||
Q_INVOKABLE float getAvatarScale();
|
||||
Q_INVOKABLE void setAvatarScale(float scale);
|
||||
|
||||
Q_INVOKABLE void setCollisionsEnabled(bool enabled);
|
||||
Q_INVOKABLE bool getCollisionsEnabled();
|
||||
Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated
|
||||
|
@ -788,13 +796,15 @@ private:
|
|||
// These are stored in SENSOR frame
|
||||
ThreadSafeValueCache<controller::Pose> _leftHandControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _rightHandControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _leftFootControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _rightFootControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _hipsControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _spine2ControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _headControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _leftArmControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _rightArmControllerPoseInSensorFrameCache{ controller::Pose() };
|
||||
ThreadSafeValueCache<FingerPosesMap> _leftHandFingerPosesInSensorFramceCache { };
|
||||
ThreadSafeValueCache<FingerPosesMap> _rightHandFingerPosesInSensorFramceCache { };
|
||||
ThreadSafeValueCache<controller::Pose> _leftFootControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _rightFootControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _hipsControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _spine2ControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _headControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _leftArmControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
ThreadSafeValueCache<controller::Pose> _rightArmControllerPoseInSensorFrameCache { controller::Pose() };
|
||||
|
||||
bool _hmdLeanRecenterEnabled = true;
|
||||
AnimPose _prePhysicsRoomPose;
|
||||
|
|
|
@ -96,7 +96,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
params.controllerPoses[Rig::ControllerType_RightArm] = AnimPose::identity;
|
||||
params.controllerActiveFlags[Rig::ControllerType_RightArm] = false;
|
||||
}
|
||||
|
||||
|
||||
auto avatarLeftArmPose = myAvatar->getLeftArmControllerPoseInAvatarFrame();
|
||||
if (avatarLeftArmPose.isValid()) {
|
||||
AnimPose pose(avatarLeftArmPose.getRotation(), avatarLeftArmPose.getTranslation());
|
||||
|
@ -174,5 +174,50 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||
|
||||
_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
|
||||
|
||||
#include <avatars-renderer/SkeletonModel.h>
|
||||
#include "MyAvatar.h"
|
||||
|
||||
/// A skeleton loaded from a model.
|
||||
class MySkeletonModel : public SkeletonModel {
|
||||
|
@ -21,6 +22,9 @@ private:
|
|||
public:
|
||||
MySkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr);
|
||||
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||
|
||||
private:
|
||||
void updateFingers(const MyAvatar::FingerPosesMap& fingerPoses);
|
||||
};
|
||||
|
||||
#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) {
|
||||
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
|
||||
// https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine
|
||||
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) {
|
||||
// Try to connect and send message to existing interface instance
|
||||
QLocalSocket socket;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "Audio.h"
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "AudioClient.h"
|
||||
#include "ui/AvatarInputs.h"
|
||||
|
@ -49,27 +51,22 @@ float Audio::loudnessToLevel(float loudness) {
|
|||
Audio::Audio() : _devices(_contextIsHMD) {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
connect(client, &AudioClient::muteToggled, this, &Audio::onMutedChanged);
|
||||
connect(client, &AudioClient::noiseReductionChanged, this, &Audio::onNoiseReductionChanged);
|
||||
connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged);
|
||||
connect(client, &AudioClient::inputVolumeChanged, this, &Audio::onInputVolumeChanged);
|
||||
connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged);
|
||||
connect(&_devices._inputs, &AudioDeviceList::deviceChanged, this, &Audio::onInputChanged);
|
||||
enableNoiseReduction(enableNoiseReductionSetting.get());
|
||||
}
|
||||
|
||||
void Audio::setMuted(bool isMuted) {
|
||||
if (_isMuted != isMuted) {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
QMetaObject::invokeMethod(client, "toggleMute", Qt::BlockingQueuedConnection);
|
||||
|
||||
_isMuted = isMuted;
|
||||
emit mutedChanged(_isMuted);
|
||||
QMetaObject::invokeMethod(client, "toggleMute");
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::onMutedChanged() {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
bool isMuted;
|
||||
QMetaObject::invokeMethod(client, "isMuted", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isMuted));
|
||||
|
||||
bool isMuted = DependencyManager::get<AudioClient>()->isMuted();
|
||||
if (_isMuted != isMuted) {
|
||||
_isMuted = isMuted;
|
||||
emit mutedChanged(_isMuted);
|
||||
|
@ -79,11 +76,16 @@ void Audio::onMutedChanged() {
|
|||
void Audio::enableNoiseReduction(bool enable) {
|
||||
if (_enableNoiseReduction != enable) {
|
||||
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);
|
||||
_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) {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
QMetaObject::invokeMethod(client, "setInputVolume", Qt::BlockingQueuedConnection, Q_ARG(float, volume));
|
||||
|
||||
_inputVolume = volume;
|
||||
emit inputVolumeChanged(_inputVolume);
|
||||
QMetaObject::invokeMethod(client, "setInputVolume", Q_ARG(float, volume));
|
||||
}
|
||||
}
|
||||
|
||||
// different audio input devices may have different volumes
|
||||
void Audio::onInputChanged() {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
float volume;
|
||||
QMetaObject::invokeMethod(client, "getInputVolume", Qt::BlockingQueuedConnection, Q_RETURN_ARG(float, volume));
|
||||
|
||||
void Audio::onInputVolumeChanged(float volume) {
|
||||
if (_inputVolume != volume) {
|
||||
_inputVolume = volume;
|
||||
emit inputVolumeChanged(_inputVolume);
|
||||
|
|
|
@ -62,9 +62,12 @@ signals:
|
|||
void contextChanged(const QString& context);
|
||||
|
||||
public slots:
|
||||
void onMutedChanged();
|
||||
void onContextChanged();
|
||||
void onInputChanged();
|
||||
|
||||
private slots:
|
||||
void onMutedChanged();
|
||||
void onNoiseReductionChanged();
|
||||
void onInputVolumeChanged(float volume);
|
||||
void onInputLoudnessChanged(float loudness);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "AudioDevices.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 success = false;
|
||||
auto& device = _devices[row];
|
||||
_userSelection = fromUser;
|
||||
|
||||
// skip if already selected
|
||||
if (!device.selected) {
|
||||
auto client = DependencyManager::get<AudioClient>();
|
||||
QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, success),
|
||||
QMetaObject::invokeMethod(client.data(), "switchAudioDevice",
|
||||
Q_ARG(QAudio::Mode, _mode),
|
||||
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));
|
||||
|
@ -135,12 +129,12 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) {
|
|||
}
|
||||
|
||||
void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) {
|
||||
auto oldDevice = _selectedDevice;
|
||||
_selectedDevice = device;
|
||||
QModelIndex index;
|
||||
|
||||
for (auto i = 0; i < _devices.size(); ++i) {
|
||||
AudioDevice& device = _devices[i];
|
||||
|
||||
if (device.selected && device.info != _selectedDevice) {
|
||||
device.selected = false;
|
||||
} 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 dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ private:
|
|||
|
||||
static QHash<int, QByteArray> _roles;
|
||||
static Qt::ItemFlags _flags;
|
||||
|
||||
bool _userSelection { false };
|
||||
QAudio::Mode _mode;
|
||||
QAudioDeviceInfo _selectedDevice;
|
||||
QList<AudioDevice> _devices;
|
||||
|
|
|
@ -8,9 +8,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "ClipboardScriptingInterface.h"
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
ClipboardScriptingInterface::ClipboardScriptingInterface() {
|
||||
}
|
||||
|
||||
|
@ -24,7 +27,7 @@ float ClipboardScriptingInterface::getClipboardContentsLargestDimension() {
|
|||
|
||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
||||
bool retVal;
|
||||
QMetaObject::invokeMethod(qApp, "exportEntities", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(qApp, "exportEntities",
|
||||
Q_RETURN_ARG(bool, retVal),
|
||||
Q_ARG(const QString&, filename),
|
||||
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 retVal;
|
||||
QMetaObject::invokeMethod(qApp, "exportEntities", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(qApp, "exportEntities",
|
||||
Q_RETURN_ARG(bool, retVal),
|
||||
Q_ARG(const QString&, filename),
|
||||
Q_ARG(float, x),
|
||||
|
@ -45,7 +48,7 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, float
|
|||
|
||||
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
||||
bool retVal;
|
||||
QMetaObject::invokeMethod(qApp, "importEntities", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(qApp, "importEntities",
|
||||
Q_RETURN_ARG(bool, retVal),
|
||||
Q_ARG(const QString&, filename));
|
||||
return retVal;
|
||||
|
@ -53,7 +56,7 @@ bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
|||
|
||||
QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(glm::vec3 position) {
|
||||
QVector<EntityItemID> retVal;
|
||||
QMetaObject::invokeMethod(qApp, "pasteEntities", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(qApp, "pasteEntities",
|
||||
Q_RETURN_ARG(QVector<EntityItemID>, retVal),
|
||||
Q_ARG(float, position.x),
|
||||
Q_ARG(float, position.y),
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <EntityItemID.h>
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Clipboard
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <plugins/PluginManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include <trackers/MotionTracker.h>
|
||||
|
||||
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
|
||||
if (event->type() == HFActionEvent::startType()) {
|
||||
|
@ -97,86 +96,6 @@ QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
|||
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::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); }
|
||||
|
||||
|
|
|
@ -25,38 +25,6 @@
|
|||
#include <WheelEvent.h>
|
||||
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
|
||||
class ControllerScriptingInterface : public controller::ScriptingInterface {
|
||||
Q_OBJECT
|
||||
|
@ -86,8 +54,6 @@ public:
|
|||
bool isJoystickCaptured(int joystickIndex) const;
|
||||
bool areEntityClicksCaptured() const;
|
||||
|
||||
void updateInputControllers();
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void captureKeyEvents(const KeyEvent& event);
|
||||
|
@ -102,10 +68,6 @@ public slots:
|
|||
virtual glm::vec2 getViewportDimensions() 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:
|
||||
void keyPressEvent(const KeyEvent& event);
|
||||
void keyReleaseEvent(const KeyEvent& event);
|
||||
|
@ -135,8 +97,6 @@ private:
|
|||
bool _captureEntityClicks;
|
||||
|
||||
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
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <QtScript/QScriptContext>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <display-plugins/DisplayPlugin.h>
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
|
@ -152,22 +153,31 @@ QString HMDScriptingInterface::preferredAudioOutput() const {
|
|||
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>();
|
||||
offscreenUi->executeOnUiThread([offscreenUi, enabled] {
|
||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
||||
});
|
||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
||||
return qApp->getActiveDisplayPlugin()->setHandLaser(hands,
|
||||
enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None,
|
||||
color, direction);
|
||||
}
|
||||
|
||||
bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) const {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->executeOnUiThread([offscreenUi, enabled] {
|
||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
||||
});
|
||||
bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
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 sensorToWorld = myAvatar->getSensorToWorldMatrix();
|
||||
|
@ -179,11 +189,11 @@ bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enab
|
|||
color, sensorStart, sensorDirection);
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::disableExtraLaser() const {
|
||||
void HMDScriptingInterface::disableExtraLaser() {
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -51,11 +51,11 @@ public:
|
|||
Q_INVOKABLE void requestHideHandControllers();
|
||||
Q_INVOKABLE bool shouldShowHandControllers() const;
|
||||
|
||||
Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const;
|
||||
Q_INVOKABLE void disableHandLasers(int hands) const;
|
||||
Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction);
|
||||
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 void disableExtraLaser() const;
|
||||
Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction);
|
||||
Q_INVOKABLE void disableExtraLaser();
|
||||
|
||||
|
||||
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <MenuItemProperties.h>
|
||||
#include "Menu.h"
|
||||
|
||||
|
@ -43,7 +44,7 @@ bool MenuScriptingInterface::menuExists(const QString& menu) {
|
|||
return Menu::getInstance()->menuExists(menu);
|
||||
}
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "menuExists", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuExists",
|
||||
Q_RETURN_ARG(bool, result),
|
||||
Q_ARG(const QString&, menu));
|
||||
return result;
|
||||
|
@ -86,7 +87,7 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString&
|
|||
return Menu::getInstance()->menuItemExists(menu, menuitem);
|
||||
}
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "menuItemExists", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuItemExists",
|
||||
Q_RETURN_ARG(bool, result),
|
||||
Q_ARG(const QString&, menu),
|
||||
Q_ARG(const QString&, menuitem));
|
||||
|
@ -114,7 +115,7 @@ bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) {
|
|||
return Menu::getInstance()->isOptionChecked(menuOption);
|
||||
}
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "isOptionChecked", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isOptionChecked",
|
||||
Q_RETURN_ARG(bool, result),
|
||||
Q_ARG(const QString&, menuOption));
|
||||
return result;
|
||||
|
@ -131,7 +132,7 @@ bool MenuScriptingInterface::isMenuEnabled(const QString& menuOption) {
|
|||
return Menu::getInstance()->isOptionChecked(menuOption);
|
||||
}
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "isMenuEnabled", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isMenuEnabled",
|
||||
Q_RETURN_ARG(bool, result),
|
||||
Q_ARG(const QString&, menuOption));
|
||||
return result;
|
||||
|
@ -157,7 +158,7 @@ bool MenuScriptingInterface::isInfoViewVisible(const QString& path) {
|
|||
}
|
||||
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
|
@ -57,20 +58,25 @@ void TestScriptingInterface::waitIdle() {
|
|||
}
|
||||
|
||||
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_BINARY_ROOT = "https://hifi-public.s3.amazonaws.com/test_scene_data/";
|
||||
static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/";
|
||||
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/");
|
||||
auto tree = qApp->getEntities()->getTree();
|
||||
auto treeIsClient = tree->getIsClient();
|
||||
// Force the tree to accept the load regardless of permissions
|
||||
tree->setIsClient(false);
|
||||
auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json");
|
||||
tree->setIsClient(treeIsClient);
|
||||
return result;
|
||||
}).toBool();
|
||||
|
||||
DependencyManager::get<ResourceManager>()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/");
|
||||
auto tree = qApp->getEntities()->getTree();
|
||||
auto treeIsClient = tree->getIsClient();
|
||||
// Force the tree to accept the load regardless of permissions
|
||||
tree->setIsClient(false);
|
||||
auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json");
|
||||
tree->setIsClient(treeIsClient);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TestScriptingInterface::startTracing(QString logrules) {
|
||||
|
|
|
@ -9,11 +9,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "WindowScriptingInterface.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QtCore/QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <SettingHandle.h>
|
||||
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
|
@ -24,8 +27,6 @@
|
|||
#include "Menu.h"
|
||||
#include "OffscreenUi.h"
|
||||
|
||||
#include "WindowScriptingInterface.h"
|
||||
|
||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
|
||||
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) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
int result;
|
||||
QMetaObject::invokeMethod(this, "openMessageBox", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "openMessageBox",
|
||||
Q_RETURN_ARG(int, result),
|
||||
Q_ARG(QString, title),
|
||||
Q_ARG(QString, text),
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <QtScript/QScriptValue>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
class CustomPromptResult {
|
||||
public:
|
||||
QVariant value;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QScrollBar>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <ScriptEngines.h>
|
||||
#include <PathUtils.h>
|
||||
|
||||
|
@ -115,7 +116,7 @@ void JSConsole::executeCommand(const QString& command) {
|
|||
|
||||
QScriptValue JSConsole::executeCommandInWatcher(const QString& command) {
|
||||
QScriptValue result;
|
||||
QMetaObject::invokeMethod(_scriptEngine, "evaluate", Qt::ConnectionType::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(_scriptEngine, "evaluate",
|
||||
Q_RETURN_ARG(QScriptValue, result),
|
||||
Q_ARG(const QString&, command),
|
||||
Q_ARG(const QString&, _consoleFileName));
|
||||
|
|
|
@ -45,11 +45,13 @@ Image3DOverlay::~Image3DOverlay() {
|
|||
}
|
||||
|
||||
void Image3DOverlay::update(float deltatime) {
|
||||
#if OVERLAY_PANELS
|
||||
if (usecTimestampNow() > _transformExpiry) {
|
||||
Transform transform = getTransform();
|
||||
applyTransformTo(transform);
|
||||
setTransform(transform);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Image3DOverlay::render(RenderArgs* args) {
|
||||
|
|
|
@ -84,9 +84,9 @@ public:
|
|||
void setColorPulse(float value) { _colorPulse = value; }
|
||||
void setAlphaPulse(float value) { _alphaPulse = value; }
|
||||
|
||||
virtual void setProperties(const QVariantMap& properties);
|
||||
virtual Overlay* createClone() const = 0;
|
||||
virtual QVariant getProperty(const QString& property);
|
||||
Q_INVOKABLE virtual void setProperties(const QVariantMap& properties);
|
||||
Q_INVOKABLE virtual Overlay* createClone() const = 0;
|
||||
Q_INVOKABLE virtual QVariant getProperty(const QString& property);
|
||||
|
||||
render::ItemID getRenderItemID() const { return _renderItemID; }
|
||||
void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; }
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "OverlayPanel.h"
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
|
||||
#include <QVariant>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <DependencyManager.h>
|
||||
|
@ -185,3 +187,4 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) {
|
|||
pointTransformAtCamera(transform, getOffsetRotation());
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
#include "Billboardable.h"
|
||||
#include "Overlay.h"
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
class PropertyBinding {
|
||||
public:
|
||||
PropertyBinding() {}
|
||||
|
@ -80,4 +81,6 @@ private:
|
|||
QScriptEngine* _scriptEngine;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // hifi_OverlayPanel_h
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <QtScript/QScriptValueIterator>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include <render/Scene.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
@ -39,34 +40,39 @@
|
|||
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
||||
|
||||
void Overlays::cleanupAllOverlays() {
|
||||
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
||||
{
|
||||
QWriteLocker lock(&_lock);
|
||||
QWriteLocker deleteLock(&_deleteLock);
|
||||
foreach(Overlay::Pointer overlay, _overlaysHUD) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
foreach(Overlay::Pointer overlay, _overlaysWorld) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
_overlaysHUD.clear();
|
||||
_overlaysWorld.clear();
|
||||
_panels.clear();
|
||||
QMutexLocker locker(&_mutex);
|
||||
overlaysHUD.swap(_overlaysHUD);
|
||||
overlaysWorld.swap(_overlaysWorld);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void Overlays::init() {
|
||||
#if OVERLAY_PANELS
|
||||
_scriptEngine = new QScriptEngine();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
|
||||
{
|
||||
QWriteLocker lock(&_lock);
|
||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
||||
QMutexLocker locker(&_mutex);
|
||||
foreach(const auto& thisOverlay, _overlaysHUD) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
foreach(Overlay::Pointer thisOverlay, _overlaysWorld) {
|
||||
foreach(const auto& thisOverlay, _overlaysWorld) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
}
|
||||
|
@ -80,8 +86,6 @@ void Overlays::cleanupOverlaysToDelete() {
|
|||
render::Transaction transaction;
|
||||
|
||||
{
|
||||
QWriteLocker lock(&_deleteLock);
|
||||
|
||||
do {
|
||||
Overlay::Pointer overlay = _overlaysToDelete.takeLast();
|
||||
|
||||
|
@ -100,7 +104,6 @@ void Overlays::cleanupOverlaysToDelete() {
|
|||
|
||||
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(render_overlays, __FUNCTION__);
|
||||
QReadLocker lock(&_lock);
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -111,7 +114,7 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
|
|||
int height = size.y;
|
||||
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
|
||||
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
||||
|
||||
// Reset all batch pipeline settings between overlay
|
||||
|
@ -126,16 +129,17 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
void Overlays::disable() {
|
||||
QWriteLocker lock(&_lock);
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
void Overlays::enable() {
|
||||
QWriteLocker lock(&_lock);
|
||||
_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 {
|
||||
QMutexLocker locker(&_mutex);
|
||||
if (_overlaysHUD.contains(id)) {
|
||||
return _overlaysHUD[id];
|
||||
}
|
||||
|
@ -146,6 +150,12 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
if (type == ImageOverlay::TYPE) {
|
||||
|
@ -185,19 +195,22 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties)
|
|||
return UNKNOWN_OVERLAY_ID;
|
||||
}
|
||||
|
||||
OverlayID Overlays::addOverlay(Overlay::Pointer overlay) {
|
||||
QWriteLocker lock(&_lock);
|
||||
OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
||||
OverlayID thisID = OverlayID(QUuid::createUuid());
|
||||
overlay->setOverlayID(thisID);
|
||||
overlay->setStackOrder(_stackOrder++);
|
||||
if (overlay->is3D()) {
|
||||
_overlaysWorld[thisID] = overlay;
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
_overlaysWorld[thisID] = overlay;
|
||||
}
|
||||
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
overlay->addToScene(overlay, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
} else {
|
||||
QMutexLocker locker(&_mutex);
|
||||
_overlaysHUD[thisID] = overlay;
|
||||
}
|
||||
|
||||
|
@ -205,14 +218,22 @@ OverlayID Overlays::addOverlay(Overlay::Pointer overlay) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
if (thisOverlay) {
|
||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone()));
|
||||
#if OVERLAY_PANELS
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
||||
if (attachable && attachable->getParentPanel()) {
|
||||
attachable->getParentPanel()->addChild(cloneId);
|
||||
}
|
||||
#endif
|
||||
return cloneId;
|
||||
}
|
||||
|
||||
|
@ -220,21 +241,32 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
|||
}
|
||||
|
||||
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);
|
||||
if (thisOverlay) {
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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();
|
||||
bool success = true;
|
||||
QWriteLocker lock(&_lock);
|
||||
for (const auto& key : map.keys()) {
|
||||
OverlayID id = OverlayID(key);
|
||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||
|
@ -249,10 +281,15 @@ bool Overlays::editOverlays(const QVariant& propertiesById) {
|
|||
}
|
||||
|
||||
void Overlays::deleteOverlay(OverlayID id) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "deleteOverlay", Q_ARG(OverlayID, id));
|
||||
return;
|
||||
}
|
||||
|
||||
Overlay::Pointer overlayToDelete;
|
||||
|
||||
{
|
||||
QWriteLocker lock(&_lock);
|
||||
QMutexLocker locker(&_mutex);
|
||||
if (_overlaysHUD.contains(id)) {
|
||||
overlayToDelete = _overlaysHUD.take(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);
|
||||
if (attachable && attachable->getParentPanel()) {
|
||||
attachable->getParentPanel()->removeChild(id);
|
||||
attachable->setParentPanel(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
QWriteLocker lock(&_deleteLock);
|
||||
_overlaysToDelete.push_back(overlayToDelete);
|
||||
|
||||
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);
|
||||
if (overlay) {
|
||||
return overlay->getType();
|
||||
|
@ -283,6 +326,12 @@ QString Overlays::getOverlayType(OverlayID overlayId) const {
|
|||
}
|
||||
|
||||
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);
|
||||
if (thisOverlay) {
|
||||
return qobject_cast<QObject*>(&(*thisOverlay));
|
||||
|
@ -290,6 +339,7 @@ QObject* Overlays::getOverlayObject(OverlayID id) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
OverlayID Overlays::getParentPanel(OverlayID childId) const {
|
||||
Overlay::Pointer overlay = getOverlay(childId);
|
||||
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) {
|
||||
glm::vec2 pointCopy = point;
|
||||
QReadLocker lock(&_lock);
|
||||
if (QThread::currentThread() != thread()) {
|
||||
OverlayID result;
|
||||
BLOCKING_INVOKE_METHOD(this, "getOverlayAtPoint", Q_RETURN_ARG(OverlayID, result), Q_ARG(glm::vec2, point));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!_enabled) {
|
||||
return UNKNOWN_OVERLAY_ID;
|
||||
}
|
||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysHUD);
|
||||
|
||||
const float LARGE_NEGATIVE_FLOAT = -9999999;
|
||||
glm::vec3 origin(pointCopy.x, pointCopy.y, LARGE_NEGATIVE_FLOAT);
|
||||
glm::vec3 direction(0, 0, 1);
|
||||
glm::vec3 thisSurfaceNormal;
|
||||
QMutexLocker locker(&_mutex);
|
||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysHUD);
|
||||
unsigned int bestStackOrder = 0;
|
||||
OverlayID bestOverlayID = UNKNOWN_OVERLAY_ID;
|
||||
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
OverlayID thisID = i.key();
|
||||
if (!i.value()->is3D()) {
|
||||
auto thisOverlay = std::dynamic_pointer_cast<Overlay2D>(i.value());
|
||||
if (thisOverlay && thisOverlay->getVisible() && thisOverlay->isLoaded() &&
|
||||
thisOverlay->getBoundingRect().contains(pointCopy.x, pointCopy.y, false)) {
|
||||
if (thisOverlay->getStackOrder() > bestStackOrder) {
|
||||
bestOverlayID = thisID;
|
||||
bestStackOrder = thisOverlay->getStackOrder();
|
||||
}
|
||||
auto thisOverlay = std::dynamic_pointer_cast<Overlay2D>(i.value());
|
||||
if (thisOverlay && thisOverlay->getVisible() && thisOverlay->isLoaded() &&
|
||||
thisOverlay->getBoundingRect().contains(point.x, point.y, false)) {
|
||||
if (thisOverlay->getStackOrder() > bestStackOrder) {
|
||||
bestOverlayID = i.key();
|
||||
bestStackOrder = thisOverlay->getStackOrder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,9 +413,14 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
|||
}
|
||||
|
||||
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;
|
||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||
QReadLocker lock(&_lock);
|
||||
if (thisOverlay && thisOverlay->supportsGetProperty()) {
|
||||
result.value = thisOverlay->getProperty(property);
|
||||
}
|
||||
|
@ -405,10 +458,22 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR
|
|||
const QVector<OverlayID>& overlaysToInclude,
|
||||
const QVector<OverlayID>& overlaysToDiscard,
|
||||
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();
|
||||
bool bestIsFront = false;
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
RayToOverlayIntersectionResult result;
|
||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
||||
while (i.hasNext()) {
|
||||
|
@ -448,16 +513,6 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR
|
|||
return result;
|
||||
}
|
||||
|
||||
RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() :
|
||||
intersects(false),
|
||||
overlayID(UNKNOWN_OVERLAY_ID),
|
||||
distance(0),
|
||||
face(),
|
||||
intersection(),
|
||||
extraInfo()
|
||||
{
|
||||
}
|
||||
|
||||
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) {
|
||||
auto obj = engine->newObject();
|
||||
obj.setProperty("intersects", value.intersects);
|
||||
|
@ -531,7 +586,12 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar
|
|||
}
|
||||
|
||||
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);
|
||||
if (!thisOverlay) {
|
||||
return false; // not found
|
||||
|
@ -539,14 +599,27 @@ bool Overlays::isLoaded(OverlayID id) {
|
|||
return thisOverlay->isLoaded();
|
||||
}
|
||||
|
||||
QSizeF Overlays::textSize(OverlayID id, const QString& text) const {
|
||||
Overlay::Pointer thisOverlay = _overlaysHUD[id];
|
||||
QSizeF Overlays::textSize(OverlayID id, const QString& text) {
|
||||
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 (auto textOverlay = std::dynamic_pointer_cast<TextOverlay>(thisOverlay)) {
|
||||
return textOverlay->textSize(text);
|
||||
}
|
||||
} else {
|
||||
thisOverlay = _overlaysWorld[id];
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
thisOverlay = _overlaysWorld[id];
|
||||
}
|
||||
if (auto text3dOverlay = std::dynamic_pointer_cast<Text3DOverlay>(thisOverlay)) {
|
||||
return text3dOverlay->textSize(text);
|
||||
}
|
||||
|
@ -554,6 +627,7 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) const {
|
|||
return QSizeF(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) {
|
||||
QWriteLocker lock(&_lock);
|
||||
|
||||
|
@ -607,8 +681,16 @@ void Overlays::deletePanel(OverlayID panelId) {
|
|||
|
||||
emit panelDeleted(panelId);
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -636,20 +718,43 @@ void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent 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();
|
||||
}
|
||||
|
||||
void Overlays::setKeyboardFocusOverlay(OverlayID id) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setKeyboardFocusOverlay", Q_ARG(OverlayID, id));
|
||||
return;
|
||||
}
|
||||
|
||||
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>();
|
||||
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>();
|
||||
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);
|
||||
|
||||
QReadLocker lock(&_lock);
|
||||
auto position = thisOverlay->getPosition();
|
||||
auto rotation = thisOverlay->getRotation();
|
||||
auto dimensions = thisOverlay->getSize();
|
||||
|
@ -854,9 +958,14 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
|||
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;
|
||||
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);
|
||||
int checked = 0;
|
||||
while (i.hasNext()) {
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
#include <PointerEvent.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
#include "OverlayPanel.h"
|
||||
|
||||
#include "PanelAttachable.h"
|
||||
#include "OverlayPanel.h"
|
||||
|
||||
class PickRay;
|
||||
|
||||
|
@ -41,6 +42,8 @@ Q_DECLARE_METATYPE(OverlayPropertyResult);
|
|||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value);
|
||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value);
|
||||
|
||||
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
||||
|
||||
/**jsdoc
|
||||
* @typedef Overlays.RayToOverlayIntersectionResult
|
||||
* @property {bool} intersects True if the PickRay intersected with a 3D overlay.
|
||||
|
@ -51,10 +54,9 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPro
|
|||
*/
|
||||
class RayToOverlayIntersectionResult {
|
||||
public:
|
||||
RayToOverlayIntersectionResult();
|
||||
bool intersects;
|
||||
OverlayID overlayID;
|
||||
float distance;
|
||||
bool intersects { false };
|
||||
OverlayID overlayID { UNKNOWN_OVERLAY_ID };
|
||||
float distance { 0 };
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
glm::vec3 intersection;
|
||||
|
@ -77,8 +79,6 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
|||
* @namespace Overlays
|
||||
*/
|
||||
|
||||
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
||||
|
||||
class Overlays : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -94,11 +94,13 @@ public:
|
|||
void enable();
|
||||
|
||||
Overlay::Pointer getOverlay(OverlayID id) const;
|
||||
#if OVERLAY_PANELS
|
||||
OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; }
|
||||
#endif
|
||||
|
||||
/// adds an overlay that's already been created
|
||||
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 mouseDoublePressEvent(QMouseEvent* event);
|
||||
|
@ -156,7 +158,7 @@ public slots:
|
|||
* @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.
|
||||
*/
|
||||
QString getOverlayType(OverlayID overlayId) const;
|
||||
QString getOverlayType(OverlayID overlayId);
|
||||
|
||||
/**jsdoc
|
||||
* Get the overlay Script object.
|
||||
|
@ -215,7 +217,7 @@ public slots:
|
|||
* @param {float} radius search 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
|
||||
* 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.
|
||||
* @return {Vec2} The size of the text.
|
||||
*/
|
||||
QSizeF textSize(OverlayID id, const QString& text) const;
|
||||
QSizeF textSize(OverlayID id, const QString& text);
|
||||
|
||||
/**jsdoc
|
||||
* Get the width of the virtual 2D HUD.
|
||||
|
@ -245,7 +247,7 @@ public slots:
|
|||
* @function Overlays.width
|
||||
* @return {float} The width of the 2D HUD.
|
||||
*/
|
||||
float width() const;
|
||||
float width();
|
||||
|
||||
/**jsdoc
|
||||
* Get the height of the virtual 2D HUD.
|
||||
|
@ -253,11 +255,12 @@ public slots:
|
|||
* @function Overlays.height
|
||||
* @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
|
||||
bool isAddedOverlay(OverlayID id);
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
OverlayID getParentPanel(OverlayID childId) const;
|
||||
void setParentPanel(OverlayID childId, OverlayID panelId);
|
||||
|
||||
|
@ -279,6 +282,8 @@ public slots:
|
|||
/// return true if there is a panel with that id else false
|
||||
bool isAddedPanel(OverlayID id) { return _panels.contains(id); }
|
||||
|
||||
#endif
|
||||
|
||||
void sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
void sendMouseReleaseOnOverlay(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 sendHoverLeaveOverlay(OverlayID id, PointerEvent event);
|
||||
|
||||
OverlayID getKeyboardFocusOverlay() const;
|
||||
OverlayID getKeyboardFocusOverlay();
|
||||
void setKeyboardFocusOverlay(OverlayID id);
|
||||
|
||||
signals:
|
||||
|
@ -314,15 +319,18 @@ signals:
|
|||
private:
|
||||
void cleanupOverlaysToDelete();
|
||||
|
||||
mutable QMutex _mutex;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||
#if OVERLAY_PANELS
|
||||
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
||||
#endif
|
||||
QList<Overlay::Pointer> _overlaysToDelete;
|
||||
unsigned int _stackOrder { 1 };
|
||||
|
||||
QReadWriteLock _lock;
|
||||
QReadWriteLock _deleteLock;
|
||||
#if OVERLAY_PANELS
|
||||
QScriptEngine* _scriptEngine;
|
||||
#endif
|
||||
bool _enabled = true;
|
||||
|
||||
PointerEvent calculatePointerEvent(Overlay::Pointer overlay, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
|
||||
|
@ -331,7 +339,7 @@ private:
|
|||
OverlayID _currentClickingOnOverlayID { 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>& overlaysToDiscard,
|
||||
bool visibleOnly = false, bool collidableOnly = false);
|
||||
|
|
|
@ -16,11 +16,15 @@
|
|||
#include "OverlayPanel.h"
|
||||
|
||||
bool PanelAttachable::getParentVisible() const {
|
||||
#if OVERLAY_PANELS
|
||||
if (getParentPanel()) {
|
||||
return getParentPanel()->getVisible() && getParentPanel()->getParentVisible();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
QVariant PanelAttachable::getProperty(const QString& property) {
|
||||
|
@ -61,11 +65,13 @@ void PanelAttachable::applyTransformTo(Transform& transform, bool force) {
|
|||
if (force || usecTimestampNow() > _transformExpiry) {
|
||||
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
||||
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
||||
#if OVERLAY_PANELS
|
||||
if (getParentPanel()) {
|
||||
getParentPanel()->applyTransformTo(transform, true);
|
||||
transform.postTranslate(getOffsetPosition());
|
||||
transform.postRotate(getOffsetRotation());
|
||||
transform.postScale(getOffsetScale());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#ifndef hifi_PanelAttachable_h
|
||||
#define hifi_PanelAttachable_h
|
||||
|
||||
#define OVERLAY_PANELS 0
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -39,18 +41,21 @@
|
|||
#include <QUuid>
|
||||
|
||||
class OverlayPanel;
|
||||
|
||||
class PanelAttachable {
|
||||
public:
|
||||
// getters
|
||||
#if OVERLAY_PANELS
|
||||
std::shared_ptr<OverlayPanel> getParentPanel() const { return _parentPanel; }
|
||||
#endif
|
||||
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
||||
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
||||
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
||||
bool getParentVisible() const;
|
||||
|
||||
// setters
|
||||
#if OVERLAY_PANELS
|
||||
void setParentPanel(std::shared_ptr<OverlayPanel> panel) { _parentPanel = panel; }
|
||||
#endif
|
||||
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
||||
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
||||
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
||||
|
@ -66,7 +71,9 @@ protected:
|
|||
quint64 _transformExpiry = 0;
|
||||
|
||||
private:
|
||||
#if OVERLAY_PANELS
|
||||
std::shared_ptr<OverlayPanel> _parentPanel = nullptr;
|
||||
#endif
|
||||
Transform _offset;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,21 +32,20 @@ QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay)
|
|||
}
|
||||
|
||||
void QmlOverlay::buildQmlElement(const QUrl& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "buildQmlElement", Q_ARG(QUrl, url));
|
||||
return;
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->returnFromUiThread([=] {
|
||||
offscreenUi->load(url, [=](QQmlContext* context, QObject* object) {
|
||||
QQuickItem* rawPtr = dynamic_cast<QQuickItem*>(object);
|
||||
// Create a shared ptr with a custom deleter lambda, that calls deleteLater
|
||||
_qmlElement = std::shared_ptr<QQuickItem>(rawPtr, [](QQuickItem* ptr) {
|
||||
if (ptr) {
|
||||
ptr->deleteLater();
|
||||
}
|
||||
});
|
||||
offscreenUi->load(url, [=](QQmlContext* context, QObject* object) {
|
||||
QQuickItem* rawPtr = dynamic_cast<QQuickItem*>(object);
|
||||
// Create a shared ptr with a custom deleter lambda, that calls deleteLater
|
||||
_qmlElement = std::shared_ptr<QQuickItem>(rawPtr, [](QQuickItem* ptr) {
|
||||
if (ptr) {
|
||||
ptr->deleteLater();
|
||||
}
|
||||
});
|
||||
while (!_qmlElement) {
|
||||
qApp->processEvents();
|
||||
}
|
||||
return QVariant();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -55,20 +54,23 @@ QmlOverlay::~QmlOverlay() {
|
|||
}
|
||||
|
||||
void QmlOverlay::setProperties(const QVariantMap& properties) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setProperties", Q_ARG(QVariantMap, properties));
|
||||
return;
|
||||
}
|
||||
|
||||
Overlay2D::setProperties(properties);
|
||||
auto bounds = _bounds;
|
||||
std::weak_ptr<QQuickItem> weakQmlElement = _qmlElement;
|
||||
DependencyManager::get<OffscreenUi>()->executeOnUiThread([weakQmlElement, bounds, properties] {
|
||||
// check to see if qmlElement still exists
|
||||
auto qmlElement = weakQmlElement.lock();
|
||||
if (qmlElement) {
|
||||
qmlElement->setX(bounds.left());
|
||||
qmlElement->setY(bounds.top());
|
||||
qmlElement->setWidth(bounds.width());
|
||||
qmlElement->setHeight(bounds.height());
|
||||
QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties));
|
||||
}
|
||||
});
|
||||
// check to see if qmlElement still exists
|
||||
auto qmlElement = weakQmlElement.lock();
|
||||
if (qmlElement) {
|
||||
qmlElement->setX(bounds.left());
|
||||
qmlElement->setY(bounds.top());
|
||||
qmlElement->setWidth(bounds.width());
|
||||
qmlElement->setHeight(bounds.height());
|
||||
QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties));
|
||||
}
|
||||
}
|
||||
|
||||
void QmlOverlay::render(RenderArgs* args) {
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
void render(RenderArgs* args) override;
|
||||
|
||||
private:
|
||||
void buildQmlElement(const QUrl& url);
|
||||
Q_INVOKABLE void buildQmlElement(const QUrl& url);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<QQuickItem> _qmlElement;
|
||||
|
|
|
@ -9,15 +9,18 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AnimationCache.h"
|
||||
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include "AnimationCache.h"
|
||||
#include "AnimationLogging.h"
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "AnimationLogging.h"
|
||||
|
||||
int animationPointerMetaTypeId = qRegisterMetaType<AnimationPointer>();
|
||||
|
||||
AnimationCache::AnimationCache(QObject* parent) :
|
||||
|
@ -31,7 +34,7 @@ AnimationCache::AnimationCache(QObject* parent) :
|
|||
AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AnimationPointer result;
|
||||
QMetaObject::invokeMethod(this, "getAnimation", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "getAnimation",
|
||||
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
|
@ -97,7 +100,7 @@ bool Animation::isLoaded() const {
|
|||
QStringList Animation::getJointNames() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(const_cast<Animation*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<Animation*>(this), "getJointNames",
|
||||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
|
@ -111,7 +114,7 @@ QStringList Animation::getJointNames() const {
|
|||
QVector<FBXAnimationFrame> Animation::getFrames() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -259,10 +259,21 @@ void AudioClient::customDeleter() {
|
|||
void AudioClient::cleanupBeforeQuit() {
|
||||
// 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
|
||||
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();
|
||||
|
||||
_checkDevicesTimer->stop();
|
||||
guard.trigger();
|
||||
}
|
||||
|
||||
void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) {
|
||||
|
@ -1335,6 +1346,14 @@ void AudioClient::toggleMute() {
|
|||
emit muteToggled();
|
||||
}
|
||||
|
||||
void AudioClient::setNoiseReduction(bool enable) {
|
||||
if (_isNoiseGateEnabled != enable) {
|
||||
_isNoiseGateEnabled = enable;
|
||||
emit noiseReductionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AudioClient::setIsStereoInput(bool isStereoInput) {
|
||||
if (isStereoInput != _isStereoInput) {
|
||||
_isStereoInput = isStereoInput;
|
||||
|
@ -1446,6 +1465,8 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
|
|||
_audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this);
|
||||
_numInputCallbackBytes = calculateNumberOfInputCallbackBytes(_inputFormat);
|
||||
_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?
|
||||
int numFrameSamples = calculateNumberOfFrameSamples(_numInputCallbackBytes);
|
||||
|
@ -1703,7 +1724,7 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) {
|
|||
|
||||
// produce an oriented angle about the y-axis
|
||||
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;
|
||||
|
||||
} else {
|
||||
|
@ -1847,3 +1868,10 @@ void AudioClient::setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 sca
|
|||
void AudioClient::startThread() {
|
||||
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;
|
||||
|
||||
void setNoiseReduction(bool isNoiseGateEnabled) { _isNoiseGateEnabled = isNoiseGateEnabled; }
|
||||
void setNoiseReduction(bool isNoiseGateEnabled);
|
||||
bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; }
|
||||
|
||||
void toggleLocalEcho() { _shouldEchoLocally = !_shouldEchoLocally; }
|
||||
void toggleServerEcho() { _shouldEchoToServer = !_shouldEchoToServer; }
|
||||
|
@ -197,7 +198,7 @@ public slots:
|
|||
bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName);
|
||||
|
||||
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 setReverbOptions(const AudioEffectOptions* options);
|
||||
|
||||
|
@ -207,7 +208,9 @@ public slots:
|
|||
void saveSettings();
|
||||
|
||||
signals:
|
||||
bool muteToggled();
|
||||
void inputVolumeChanged(float volume);
|
||||
void muteToggled();
|
||||
void noiseReductionChanged();
|
||||
void mutedByMixer();
|
||||
void inputReceived(const QByteArray& inputSamples);
|
||||
void inputLoudnessChanged(float loudness);
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
// 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 "SoundCache.h"
|
||||
|
||||
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) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
SharedSoundPointer result;
|
||||
QMetaObject::invokeMethod(this, "getSound", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "getSound",
|
||||
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <glm/gtx/transform.hpp>
|
||||
#include <glm/gtx/vector_query.hpp>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <EntityTreeRenderer.h>
|
||||
#include <NodeList.h>
|
||||
|
@ -1010,7 +1011,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
|||
int Avatar::getJointIndex(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1024,7 +1025,7 @@ int Avatar::getJointIndex(const QString& name) const {
|
|||
QStringList Avatar::getJointNames() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<Avatar*>(this), "getJointNames",
|
||||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
|
@ -1034,7 +1035,7 @@ QStringList Avatar::getJointNames() const {
|
|||
glm::vec3 Avatar::getJointPosition(int index) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return position;
|
||||
}
|
||||
|
@ -1046,7 +1047,7 @@ glm::vec3 Avatar::getJointPosition(int index) const {
|
|||
glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return position;
|
||||
}
|
||||
|
@ -1105,7 +1106,7 @@ static std::shared_ptr<Model> allocateAttachmentModel(bool isSoft, const Rig& ri
|
|||
|
||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAttachmentData", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <QVariantGLM.h>
|
||||
#include <Transform.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
|
@ -1227,7 +1228,7 @@ bool AvatarData::isJointDataValid(int index) const {
|
|||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1240,7 +1241,7 @@ glm::quat AvatarData::getJointRotation(int index) const {
|
|||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1255,7 +1256,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const {
|
|||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1266,7 +1267,7 @@ glm::vec3 AvatarData::getJointTranslation(int index) const {
|
|||
glm::vec3 AvatarData::getJointTranslation(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1344,7 +1345,7 @@ void AvatarData::clearJointData(const QString& name) {
|
|||
bool AvatarData::isJointDataValid(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1354,7 +1355,7 @@ bool AvatarData::isJointDataValid(const QString& name) const {
|
|||
glm::quat AvatarData::getJointRotation(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1364,8 +1365,7 @@ glm::quat AvatarData::getJointRotation(const QString& name) const {
|
|||
QVector<glm::quat> AvatarData::getJointRotations() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<glm::quat> result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
||||
"getJointRotations", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointRotations",
|
||||
Q_RETURN_ARG(QVector<glm::quat>, result));
|
||||
return result;
|
||||
}
|
||||
|
@ -1380,8 +1380,7 @@ QVector<glm::quat> AvatarData::getJointRotations() const {
|
|||
void AvatarData::setJointRotations(QVector<glm::quat> jointRotations) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<glm::quat> result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
||||
"setJointRotations", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "setJointRotations",
|
||||
Q_ARG(QVector<glm::quat>, jointRotations));
|
||||
}
|
||||
QWriteLocker writeLock(&_jointDataLock);
|
||||
|
@ -1398,8 +1397,7 @@ void AvatarData::setJointRotations(QVector<glm::quat> jointRotations) {
|
|||
QVector<glm::vec3> AvatarData::getJointTranslations() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<glm::vec3> result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
||||
"getJointTranslations", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getJointTranslations",
|
||||
Q_RETURN_ARG(QVector<glm::vec3>, result));
|
||||
return result;
|
||||
}
|
||||
|
@ -1414,8 +1412,7 @@ QVector<glm::vec3> AvatarData::getJointTranslations() const {
|
|||
void AvatarData::setJointTranslations(QVector<glm::vec3> jointTranslations) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<glm::quat> result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this),
|
||||
"setJointTranslations", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "setJointTranslations",
|
||||
Q_ARG(QVector<glm::vec3>, jointTranslations));
|
||||
}
|
||||
QWriteLocker writeLock(&_jointDataLock);
|
||||
|
@ -1616,7 +1613,7 @@ void AvatarData::setDisplayName(const QString& displayName) {
|
|||
QVector<AttachmentData> AvatarData::getAttachmentData() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1978,7 +1975,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) {
|
|||
result.rotation = quatFromJsonValue(array[0]);
|
||||
result.rotationSet = true;
|
||||
result.translation = vec3FromJsonValue(array[1]);
|
||||
result.translationSet = false;
|
||||
result.translationSet = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2146,12 +2143,9 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
QVector<JointData> jointArray;
|
||||
QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray();
|
||||
jointArray.reserve(jointArrayJson.size());
|
||||
int i = 0;
|
||||
for (const auto& jointJson : jointArrayJson) {
|
||||
auto joint = jointDataFromJsonValue(jointJson);
|
||||
jointArray.push_back(joint);
|
||||
setJointData(i, joint.rotation, joint.translation);
|
||||
i++;
|
||||
}
|
||||
setRawJointData(jointArray);
|
||||
}
|
||||
|
@ -2342,7 +2336,7 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID) {
|
|||
AvatarEntityMap AvatarData::getAvatarEntityData() const {
|
||||
AvatarEntityMap result;
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -2383,7 +2377,7 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) {
|
|||
AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() {
|
||||
AvatarEntityIDs result;
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -627,6 +627,7 @@ public:
|
|||
void markIdentityDataChanged() { _identityDataChanged = true; }
|
||||
|
||||
void pushIdentitySequenceNumber() { ++_identitySequenceNumber; };
|
||||
bool hasProcessedFirstIdentity() const { return _hasProcessedFirstIdentity; }
|
||||
|
||||
float getDensity() const { return _density; }
|
||||
|
||||
|
|
|
@ -59,6 +59,48 @@ namespace controller {
|
|||
makePosePair(Action::SPINE2, "Spine2"),
|
||||
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::RIGHT_HAND_CLICK, "RightHandClick"),
|
||||
|
||||
|
|
|
@ -104,6 +104,47 @@ enum class Action {
|
|||
LEFT_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,
|
||||
};
|
||||
|
|
|
@ -101,7 +101,47 @@ Input::NamedVector StandardController::getAvailableInputs() const {
|
|||
|
||||
// Poses
|
||||
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_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(RIGHT_FOOT, "RightFoot"),
|
||||
makePair(RIGHT_ARM, "RightArm"),
|
||||
|
|
|
@ -11,14 +11,16 @@
|
|||
#include <memory>
|
||||
#include <math.h>
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QQuickWindow>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <ui/Menu.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <DependencyManager.h>
|
||||
|
@ -289,7 +291,7 @@ glm::vec2 CompositorHelper::getReticleMaximumPosition() const {
|
|||
|
||||
void CompositorHelper::sendFakeMouseEvent() {
|
||||
if (qApp->thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "sendFakeMouseEvent", Qt::BlockingQueuedConnection);
|
||||
BLOCKING_INVOKE_METHOD(this, "sendFakeMouseEvent");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <QScriptSyntaxCheckResult>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <ColorUtils.h>
|
||||
#include <AbstractScriptingServicesInterface.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
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "allocateModel", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "allocateModel",
|
||||
Q_RETURN_ARG(ModelPointer, model),
|
||||
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) {
|
||||
// Only create and delete models on the thread that owns the EntityTreeRenderer
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "updateModel", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "updateModel",
|
||||
Q_RETURN_ARG(ModelPointer, model),
|
||||
Q_ARG(ModelPointer, model),
|
||||
Q_ARG(const QString&, newUrl));
|
||||
|
|
|
@ -9,19 +9,20 @@
|
|||
// 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/gtx/transform.hpp>
|
||||
|
||||
#include "EntityScriptingInterface.h"
|
||||
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <VariantMapToScriptValue.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <SpatialParentFinder.h>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityDynamicFactoryInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
@ -1488,7 +1489,7 @@ int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString
|
|||
return -1;
|
||||
}
|
||||
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));
|
||||
return result;
|
||||
}
|
||||
|
@ -1498,7 +1499,7 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) {
|
|||
return QStringList();
|
||||
}
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(_entityTree.get(), "getJointNames", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointNames",
|
||||
Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
|||
(&::gpu::gl::GLBackend::do_getQuery),
|
||||
|
||||
(&::gpu::gl::GLBackend::do_resetStages),
|
||||
|
||||
|
||||
(&::gpu::gl::GLBackend::do_disableContextViewCorrection),
|
||||
(&::gpu::gl::GLBackend::do_restoreContextViewCorrection),
|
||||
(&::gpu::gl::GLBackend::do_disableContextStereo),
|
||||
(&::gpu::gl::GLBackend::do_restoreContextStereo),
|
||||
|
||||
|
@ -374,6 +376,13 @@ void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) {
|
|||
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) {
|
||||
|
||||
|
|
|
@ -143,6 +143,10 @@ public:
|
|||
// Reset stages
|
||||
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_restoreContextStereo(const Batch& batch, size_t paramOffset) final;
|
||||
|
||||
|
@ -333,6 +337,8 @@ protected:
|
|||
bool _skybox { false };
|
||||
Transform _view;
|
||||
CameraCorrection _correction;
|
||||
bool _viewCorrectionEnabled{ true };
|
||||
|
||||
|
||||
Mat4 _projection;
|
||||
Vec4i _viewport { 0, 0, 1, 1 };
|
||||
|
@ -400,6 +406,7 @@ protected:
|
|||
bool _invalidProgram { false };
|
||||
|
||||
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::Signature _stateSignatureCache { 0 };
|
||||
|
@ -409,6 +416,8 @@ protected:
|
|||
|
||||
PipelineStageState() {
|
||||
_cameraCorrectionBuffer.edit<CameraCorrection>() = CameraCorrection();
|
||||
_cameraCorrectionBufferIdentity.edit<CameraCorrection>() = CameraCorrection();
|
||||
_cameraCorrectionBufferIdentity._buffer->flush();
|
||||
}
|
||||
} _pipeline;
|
||||
|
||||
|
|
|
@ -77,8 +77,14 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
|||
if (_pipeline._invalidProgram) {
|
||||
glUseProgram(_pipeline._program);
|
||||
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));
|
||||
|
||||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
_pipeline._invalidProgram = false;
|
||||
|
|
|
@ -102,7 +102,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
|||
|
||||
if (_invalidView) {
|
||||
// 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?
|
||||
Transform result;
|
||||
_view.mult(result, _view, _correction.correction);
|
||||
|
|
|
@ -390,6 +390,13 @@ void Batch::resetStages() {
|
|||
ADD_COMMAND(resetStages);
|
||||
}
|
||||
|
||||
void Batch::disableContextViewCorrection() {
|
||||
ADD_COMMAND(disableContextViewCorrection);
|
||||
}
|
||||
|
||||
void Batch::restoreContextViewCorrection() {
|
||||
ADD_COMMAND(restoreContextViewCorrection);
|
||||
}
|
||||
|
||||
void Batch::disableContextStereo() {
|
||||
ADD_COMMAND(disableContextStereo);
|
||||
|
|
|
@ -217,6 +217,9 @@ public:
|
|||
// Reset the stage caches and states
|
||||
void resetStages();
|
||||
|
||||
void disableContextViewCorrection();
|
||||
void restoreContextViewCorrection();
|
||||
|
||||
void disableContextStereo();
|
||||
void restoreContextStereo();
|
||||
|
||||
|
@ -304,6 +307,9 @@ public:
|
|||
|
||||
COMMAND_resetStages,
|
||||
|
||||
COMMAND_disableContextViewCorrection,
|
||||
COMMAND_restoreContextViewCorrection,
|
||||
|
||||
COMMAND_disableContextStereo,
|
||||
COMMAND_restoreContextStereo,
|
||||
|
||||
|
|
|
@ -198,11 +198,7 @@ gpu::TexturePointer TextureCache::getTextureByHash(const std::string& hash) {
|
|||
std::unique_lock<std::mutex> lock(_texturesByHashesMutex);
|
||||
weakPointer = _texturesByHashes[hash];
|
||||
}
|
||||
auto result = weakPointer.lock();
|
||||
if (result) {
|
||||
qCWarning(modelnetworking) << "QQQ Returning live texture for hash " << hash.c_str();
|
||||
}
|
||||
return result;
|
||||
return weakPointer.lock();
|
||||
}
|
||||
|
||||
gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture) {
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <QtScript/QScriptEngine>
|
||||
#include <QtNetwork/QNetworkDiskCache>
|
||||
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
|
||||
#include "AssetRequest.h"
|
||||
#include "AssetUpload.h"
|
||||
#include "AssetUtils.h"
|
||||
|
@ -31,11 +33,12 @@
|
|||
|
||||
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){
|
||||
static_cast<AssetClient*>(dependency)->deleteLater();
|
||||
});
|
||||
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
|
||||
|
@ -105,7 +108,7 @@ void AssetClient::handleAssetMappingOperationReply(QSharedPointer<ReceivedMessag
|
|||
|
||||
MessageID messageID;
|
||||
message->readPrimitive(&messageID);
|
||||
|
||||
|
||||
AssetServerError error;
|
||||
message->readPrimitive(&error);
|
||||
|
||||
|
@ -132,13 +135,13 @@ void AssetClient::handleAssetMappingOperationReply(QSharedPointer<ReceivedMessag
|
|||
bool haveAssetServer() {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
|
||||
if (!assetServer) {
|
||||
qCWarning(asset_client) << "Could not complete AssetClient operation "
|
||||
<< "since you are not currently connected to an asset-server.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -220,14 +223,14 @@ MessageID AssetClient::getAsset(const QString& hash, DataOffset start, DataOffse
|
|||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
if (assetServer) {
|
||||
|
||||
|
||||
auto messageID = ++_currentID;
|
||||
|
||||
|
||||
auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH + sizeof(start) + sizeof(end);
|
||||
auto packet = NLPacket::create(PacketType::AssetGet, payloadSize, true);
|
||||
|
||||
|
||||
qCDebug(asset_client) << "Requesting data from" << start << "to" << end << "of" << hash << "from asset-server.";
|
||||
|
||||
|
||||
packet->writePrimitive(messageID);
|
||||
|
||||
packet->write(QByteArray::fromHex(hash.toLatin1()));
|
||||
|
@ -254,10 +257,10 @@ MessageID AssetClient::getAssetInfo(const QString& hash, GetInfoCallback callbac
|
|||
|
||||
if (assetServer) {
|
||||
auto messageID = ++_currentID;
|
||||
|
||||
|
||||
auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH;
|
||||
auto packet = NLPacket::create(PacketType::AssetGetInfo, payloadSize, true);
|
||||
|
||||
|
||||
packet->writePrimitive(messageID);
|
||||
packet->write(QByteArray::fromHex(hash.toLatin1()));
|
||||
|
||||
|
@ -278,7 +281,7 @@ void AssetClient::handleAssetGetInfoReply(QSharedPointer<ReceivedMessage> messag
|
|||
MessageID messageID;
|
||||
message->readPrimitive(&messageID);
|
||||
auto assetHash = message->read(SHA256_HASH_LENGTH);
|
||||
|
||||
|
||||
AssetServerError error;
|
||||
message->readPrimitive(&error);
|
||||
|
||||
|
@ -367,7 +370,7 @@ void AssetClient::handleAssetGetReply(QSharedPointer<ReceivedMessage> message, S
|
|||
callbacks.completeCallback(true, error, message->readAll());
|
||||
}
|
||||
|
||||
|
||||
|
||||
messageCallbackMap.erase(requestIt);
|
||||
}
|
||||
}
|
||||
|
@ -478,7 +481,7 @@ MessageID AssetClient::getAllAssetMappings(MappingOperationCallback callback) {
|
|||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
|
||||
if (assetServer) {
|
||||
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) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
|
||||
if (assetServer) {
|
||||
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>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
|
||||
if (assetServer) {
|
||||
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>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
|
||||
if (assetServer) {
|
||||
auto packetList = NLPacketList::create(PacketType::AssetUpload, QByteArray(), true, true);
|
||||
|
||||
|
@ -682,7 +685,7 @@ void AssetClient::handleAssetUploadReply(QSharedPointer<ReceivedMessage> message
|
|||
} else {
|
||||
auto hash = message->read(SHA256_HASH_LENGTH);
|
||||
hashString = hash.toHex();
|
||||
|
||||
|
||||
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 {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssetClient(const QString& cacheDir="");
|
||||
AssetClient();
|
||||
|
||||
Q_INVOKABLE GetMappingRequest* createGetMappingRequest(const AssetPath& path);
|
||||
Q_INVOKABLE GetAllMappingsRequest* createGetAllMappingsRequest();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <QtNetwork/QHostInfo>
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <ThreadHelpers.h>
|
||||
#include <LogHandler.h>
|
||||
#include <UUID.h>
|
||||
|
@ -232,7 +233,7 @@ void NodeList::processICEPingPacket(QSharedPointer<ReceivedMessage> message) {
|
|||
|
||||
void NodeList::reset() {
|
||||
if (thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "reset", Qt::BlockingQueuedConnection);
|
||||
QMetaObject::invokeMethod(this, "reset");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,22 +9,24 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ResourceCache.h"
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <assert.h>
|
||||
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <assert.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <Trace.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "NetworkAccessManager.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include "NodeList.h"
|
||||
|
||||
#include "ResourceCache.h"
|
||||
#include <Trace.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#define clamp(x, min, max) (((x) < (min)) ? (min) :\
|
||||
(((x) > (max)) ? (max) :\
|
||||
|
@ -178,7 +180,7 @@ ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) {
|
|||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
// 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_ARG(QUrl, url), Q_ARG(void*, extra));
|
||||
return result;
|
||||
|
@ -301,7 +303,7 @@ QVariantList ResourceCache::getResourceList() {
|
|||
QVariantList list;
|
||||
if (QThread::currentThread() != thread()) {
|
||||
// NOTE: invokeMethod does not allow a const QObject*
|
||||
QMetaObject::invokeMethod(this, "getResourceList", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "getResourceList",
|
||||
Q_RETURN_ARG(QVariantList, list));
|
||||
} else {
|
||||
auto resources = _resources.uniqueKeys();
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
ResourceManager::ResourceManager() {
|
||||
_thread.setObjectName("Resource Manager Thread");
|
||||
|
||||
auto assetClient = DependencyManager::set<AssetClient>(_cacheDir);
|
||||
auto assetClient = DependencyManager::set<AssetClient>();
|
||||
assetClient->moveToThread(&_thread);
|
||||
QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init);
|
||||
|
||||
|
@ -160,7 +160,3 @@ bool ResourceManager::resourceExists(const QUrl& url) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void ResourceManager::setCacheDir(const QString& cacheDir) {
|
||||
// TODO: check for existence?
|
||||
_cacheDir = cacheDir;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ private:
|
|||
PrefixMap _prefixMap;
|
||||
QMutex _prefixMapLock;
|
||||
|
||||
QString _cacheDir;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
@ -276,7 +277,7 @@ Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) {
|
|||
|
||||
void Socket::clearConnections() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "clearConnections", Qt::BlockingQueuedConnection);
|
||||
BLOCKING_INVOKE_METHOD(this, "clearConnections");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <QThread>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "DisplayPlugin.h"
|
||||
#include "InputPlugin.h"
|
||||
#include "PluginManager.h"
|
||||
|
@ -21,7 +23,7 @@ InputConfiguration::InputConfiguration() {
|
|||
QStringList InputConfiguration::inputPlugins() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(this, "inputPlugins", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "inputPlugins",
|
||||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
|
@ -42,7 +44,7 @@ QStringList InputConfiguration::inputPlugins() {
|
|||
QStringList InputConfiguration::activeInputPlugins() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(this, "activeInputPlugins", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "activeInputPlugins",
|
||||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
|
@ -64,7 +66,7 @@ QStringList InputConfiguration::activeInputPlugins() {
|
|||
QString InputConfiguration::configurationLayout(QString pluginName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QString result;
|
||||
QMetaObject::invokeMethod(this, "configurationLayout", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "configurationLayout",
|
||||
Q_RETURN_ARG(QString, result),
|
||||
Q_ARG(QString, pluginName));
|
||||
return result;
|
||||
|
@ -81,7 +83,7 @@ QString InputConfiguration::configurationLayout(QString pluginName) {
|
|||
|
||||
void InputConfiguration::setConfigurationSettings(QJsonObject configurationSettings, QString pluginName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setConfigurationSettings", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "setConfigurationSettings",
|
||||
Q_ARG(QJsonObject, configurationSettings),
|
||||
Q_ARG(QString, pluginName));
|
||||
return;
|
||||
|
@ -97,7 +99,7 @@ void InputConfiguration::setConfigurationSettings(QJsonObject configurationSetti
|
|||
QJsonObject InputConfiguration::configurationSettings(QString pluginName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QJsonObject result;
|
||||
QMetaObject::invokeMethod(this, "configurationSettings", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "configurationSettings",
|
||||
Q_RETURN_ARG(QJsonObject, result),
|
||||
Q_ARG(QString, pluginName));
|
||||
return result;
|
||||
|
@ -113,7 +115,7 @@ QJsonObject InputConfiguration::configurationSettings(QString pluginName) {
|
|||
|
||||
void InputConfiguration::calibratePlugin(QString pluginName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "calibratePlugin", Qt::BlockingQueuedConnection);
|
||||
BLOCKING_INVOKE_METHOD(this, "calibratePlugin");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -128,7 +130,7 @@ void InputConfiguration::calibratePlugin(QString pluginName) {
|
|||
bool InputConfiguration::uncalibratePlugin(QString pluginName) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(this, "uncalibratePlugin", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "uncalibratePlugin",
|
||||
Q_ARG(bool, result));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <QThread>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "ClipCache.h"
|
||||
#include "impl/PointerClip.h"
|
||||
#include "Logging.h"
|
||||
|
@ -37,7 +39,7 @@ ClipCache::ClipCache(QObject* parent) :
|
|||
NetworkClipLoaderPointer ClipCache::getClipLoader(const QUrl& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
NetworkClipLoaderPointer result;
|
||||
QMetaObject::invokeMethod(this, "getClipLoader", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(this, "getClipLoader",
|
||||
Q_RETURN_ARG(NetworkClipLoaderPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ void DeferredFrameTransform::update(RenderArgs* args) {
|
|||
args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono);
|
||||
|
||||
// Running in stero ?
|
||||
bool isStereo = args->_context->isStereo();
|
||||
bool isStereo = args->isStereo();
|
||||
if (!isStereo) {
|
||||
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono;
|
||||
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/norm.hpp>
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
|
@ -870,7 +871,7 @@ bool Model::getRelativeDefaultJointTranslation(int jointIndex, glm::vec3& transl
|
|||
QStringList Model::getJointNames() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(const_cast<Model*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
||||
BLOCKING_INVOKE_METHOD(const_cast<Model*>(this), "getJointNames",
|
||||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
|
|||
batch.setFramebuffer(blitFbo);
|
||||
|
||||
if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
if (renderArgs->_context->isStereo()) {
|
||||
if (renderArgs->isStereo()) {
|
||||
gpu::Vec4i srcRectLeft;
|
||||
srcRectLeft.z = width / 2;
|
||||
srcRectLeft.w = height;
|
||||
|
|
|
@ -459,7 +459,7 @@ void SurfaceGeometryPass::run(const render::RenderContextPointer& renderContext,
|
|||
auto diffuseVPipeline = _diffusePass.getBlurVPipeline();
|
||||
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());
|
||||
_diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport));
|
||||
_diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]);
|
||||
|
|
|
@ -34,6 +34,8 @@ in vec2 _texCoord0;
|
|||
out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
_fragColor = vec4(0.0);
|
||||
|
||||
// Grab the fragment data from the uv
|
||||
vec2 texCoord = _texCoord0.st;
|
||||
|
||||
|
|
|
@ -99,6 +99,8 @@ namespace render {
|
|||
void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); }
|
||||
void popViewFrustum() { _viewFrustums.pop(); }
|
||||
|
||||
bool isStereo() const { return _displayMode != MONO; }
|
||||
|
||||
std::shared_ptr<gpu::Context> _context;
|
||||
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer;
|
||||
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