mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' of https://github.com/highfidelity/hifi into godview
This commit is contained in:
commit
10341af819
13 changed files with 491 additions and 218 deletions
|
@ -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: {
|
||||
|
@ -641,17 +649,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();
|
||||
}
|
||||
|
||||
|
@ -717,6 +747,12 @@ Rectangle {
|
|||
|
||||
initializeButtonState();
|
||||
updateCalibrationText();
|
||||
|
||||
var data = {
|
||||
"num_pucks": settings["puckCount"]
|
||||
};
|
||||
|
||||
UserActivityLogger.logAction("mocap_ui_open_dialog", data);
|
||||
}
|
||||
|
||||
function displayTrackerConfiguration(type) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QtCore/QCommandLineParser>
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QThreadPool>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtGui/QWindow>
|
||||
|
@ -2164,48 +2165,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
|
||||
|
@ -2216,114 +2243,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
|
||||
|
@ -3623,6 +3663,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;
|
||||
|
@ -3675,6 +3842,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
|
||||
|
||||
|
||||
|
@ -3695,15 +3882,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
|
||||
|
||||
|
||||
|
|
|
@ -40,19 +40,23 @@
|
|||
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
||||
|
||||
void Overlays::cleanupAllOverlays() {
|
||||
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
||||
{
|
||||
foreach(Overlay::Pointer overlay, _overlaysHUD) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
foreach(Overlay::Pointer overlay, _overlaysWorld) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
_overlaysHUD.clear();
|
||||
_overlaysWorld.clear();
|
||||
#if OVERLAY_PANELS
|
||||
_panels.clear();
|
||||
#endif
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -63,12 +67,12 @@ void Overlays::init() {
|
|||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -110,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
|
||||
|
@ -132,7 +136,10 @@ void Overlays::enable() {
|
|||
_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];
|
||||
}
|
||||
|
@ -193,13 +200,17 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -231,9 +242,12 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
|||
|
||||
bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
BLOCKING_INVOKE_METHOD(this, "editOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id), Q_ARG(QVariant, properties));
|
||||
return result;
|
||||
// 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);
|
||||
|
@ -246,9 +260,9 @@ bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
|
|||
|
||||
bool Overlays::editOverlays(const QVariant& propertiesById) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
BLOCKING_INVOKE_METHOD(this, "editOverlays", Q_RETURN_ARG(bool, result), Q_ARG(QVariant, propertiesById));
|
||||
return result;
|
||||
// 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();
|
||||
|
@ -275,6 +289,7 @@ void Overlays::deleteOverlay(OverlayID id) {
|
|||
Overlay::Pointer overlayToDelete;
|
||||
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
if (_overlaysHUD.contains(id)) {
|
||||
overlayToDelete = _overlaysHUD.take(id);
|
||||
} else if (_overlaysWorld.contains(id)) {
|
||||
|
@ -374,30 +389,22 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
|||
return result;
|
||||
}
|
||||
|
||||
glm::vec2 pointCopy = point;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -466,6 +473,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR
|
|||
float bestDistance = std::numeric_limits<float>::max();
|
||||
bool bestIsFront = false;
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
RayToOverlayIntersectionResult result;
|
||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
||||
while (i.hasNext()) {
|
||||
|
@ -598,13 +606,20 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Overlay::Pointer thisOverlay = _overlaysHUD[id];
|
||||
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);
|
||||
}
|
||||
|
@ -675,6 +690,7 @@ bool Overlays::isAddedOverlay(OverlayID id) {
|
|||
return result;
|
||||
}
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
|
||||
}
|
||||
|
||||
|
@ -949,7 +965,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
|
||||
int checked = 0;
|
||||
while (i.hasNext()) {
|
||||
|
|
|
@ -319,6 +319,7 @@ signals:
|
|||
private:
|
||||
void cleanupOverlaysToDelete();
|
||||
|
||||
mutable QMutex _mutex;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||
#if OVERLAY_PANELS
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1821,7 +1821,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
|||
clearExceptions();
|
||||
}
|
||||
} else {
|
||||
scriptWarningMessage("Script.include() skipping evaluation of previously included url:" + url.toString());
|
||||
scriptPrintedMessage("Script.include() skipping evaluation of previously included url:" + url.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,6 @@ void moveToNewNamedThread(QObject* object, const QString& name, std::function<vo
|
|||
QThread* thread = new QThread();
|
||||
thread->setObjectName(name);
|
||||
|
||||
if (priority != QThread::InheritPriority) {
|
||||
thread->setPriority(priority);
|
||||
}
|
||||
|
||||
QString tempName = name;
|
||||
QObject::connect(thread, &QThread::started, [startCallback] {
|
||||
startCallback();
|
||||
|
@ -32,6 +28,9 @@ void moveToNewNamedThread(QObject* object, const QString& name, std::function<vo
|
|||
// put the object on the thread
|
||||
object->moveToThread(thread);
|
||||
thread->start();
|
||||
if (priority != QThread::InheritPriority) {
|
||||
thread->setPriority(priority);
|
||||
}
|
||||
}
|
||||
|
||||
void moveToNewNamedThread(QObject* object, const QString& name, QThread::Priority priority) {
|
||||
|
|
|
@ -249,6 +249,7 @@ ViveControllerManager::InputDevice::InputDevice(vr::IVRSystem*& system) : contro
|
|||
_configStringMap[Config::FeetAndHips] = QString("FeetAndHips");
|
||||
_configStringMap[Config::FeetHipsAndChest] = QString("FeetHipsAndChest");
|
||||
_configStringMap[Config::FeetHipsAndShoulders] = QString("FeetHipsAndShoulders");
|
||||
_configStringMap[Config::FeetHipsChestAndShoulders] = QString("FeetHipsChestAndShoulders");
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||
|
@ -325,6 +326,7 @@ void ViveControllerManager::InputDevice::calibrateFromUI(const controller::Input
|
|||
if (_calibrate) {
|
||||
uncalibrate();
|
||||
calibrate(inputCalibrationData);
|
||||
emitCalibrationStatus();
|
||||
_calibrate = false;
|
||||
}
|
||||
}
|
||||
|
@ -372,29 +374,23 @@ QJsonObject ViveControllerManager::InputDevice::configurationSettings() {
|
|||
Locker locker(_lock);
|
||||
QJsonObject configurationSettings;
|
||||
configurationSettings["trackerConfiguration"] = configToString(_preferedConfig);
|
||||
configurationSettings["HMDHead"] = (_headConfig == HeadConfig::HMD) ? true : false;
|
||||
configurationSettings["handController"] = (_handConfig == HandConfig::HandController) ? true : false;
|
||||
configurationSettings["HMDHead"] = (_headConfig == HeadConfig::HMD);
|
||||
configurationSettings["handController"] = (_handConfig == HandConfig::HandController);
|
||||
configurationSettings["puckCount"] = (int)_validTrackedObjects.size();
|
||||
return configurationSettings;
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::emitCalibrationStatus(const bool success) {
|
||||
void ViveControllerManager::InputDevice::emitCalibrationStatus() {
|
||||
auto inputConfiguration = DependencyManager::get<InputConfiguration>();
|
||||
QJsonObject status = QJsonObject();
|
||||
|
||||
if (_calibrated && success) {
|
||||
status["calibrated"] = _calibrated;
|
||||
status["configuration"] = configToString(_preferedConfig);
|
||||
} else if (!_calibrated && !success) {
|
||||
status["calibrated"] = _calibrated;
|
||||
status["success"] = success;
|
||||
} else if (!_calibrated && success) {
|
||||
status["calibrated"] = _calibrated;
|
||||
status["success"] = success;
|
||||
status["configuration"] = configToString(_preferedConfig);
|
||||
status["puckCount"] = (int)_validTrackedObjects.size();
|
||||
}
|
||||
status["calibrated"] = _calibrated;
|
||||
status["configuration"] = configToString(_preferedConfig);
|
||||
status["head_puck"] = (_headConfig == HeadConfig::Puck);
|
||||
status["hand_pucks"] = (_handConfig == HandConfig::Pucks);
|
||||
status["puckCount"] = (int)_validTrackedObjects.size();
|
||||
status["UI"] = _calibrate;
|
||||
|
||||
emit inputConfiguration->calibrationStatus(status); //inputConfiguration->calibrated(status);
|
||||
emit inputConfiguration->calibrationStatus(status);
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) {
|
||||
|
@ -437,12 +433,29 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde
|
|||
}
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::sendUserActivityData(QString activity) {
|
||||
QJsonObject jsonData = {
|
||||
{"num_pucks", (int)_validTrackedObjects.size()},
|
||||
{"configuration", configToString(_preferedConfig)},
|
||||
{"head_puck", (_headConfig == HeadConfig::Puck) ? true : false},
|
||||
{"hand_pucks", (_handConfig == HandConfig::Pucks) ? true : false}
|
||||
};
|
||||
|
||||
UserActivityLogger::getInstance().logAction(activity, jsonData);
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::calibrateOrUncalibrate(const controller::InputCalibrationData& inputCalibration) {
|
||||
if (!_calibrated) {
|
||||
calibrate(inputCalibration);
|
||||
if (_calibrated) {
|
||||
sendUserActivityData("mocap_button_success");
|
||||
} else {
|
||||
sendUserActivityData("mocap_button_fail");
|
||||
}
|
||||
emitCalibrationStatus();
|
||||
} else {
|
||||
uncalibrate();
|
||||
emitCalibrationStatus(true);
|
||||
sendUserActivityData("mocap_button_uncalibrate");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,7 +467,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr
|
|||
|
||||
if (puckCount == 0) {
|
||||
uncalibrate();
|
||||
emitCalibrationStatus(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -473,10 +485,8 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr
|
|||
|
||||
if (!headConfigured || !handsConfigured || !bodyConfigured) {
|
||||
uncalibrate();
|
||||
emitCalibrationStatus(false);
|
||||
} else {
|
||||
_calibrated = true;
|
||||
emitCalibrationStatus(true);
|
||||
qDebug() << "PuckCalibration: " << configToString(_config) << " Configuration Successful";
|
||||
}
|
||||
}
|
||||
|
@ -566,8 +576,6 @@ bool ViveControllerManager::InputDevice::configureBody(glm::mat4& defaultToRefer
|
|||
return true;
|
||||
}
|
||||
qDebug() << "Puck Calibration: " << configToString(_config) << " Config Failed: Could not meet the minimal # of pucks";
|
||||
uncalibrate();
|
||||
emitCalibrationStatus(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ private:
|
|||
void calibrateOrUncalibrate(const controller::InputCalibrationData& inputCalibration);
|
||||
void calibrate(const controller::InputCalibrationData& inputCalibration);
|
||||
void uncalibrate();
|
||||
void sendUserActivityData(QString activity);
|
||||
void configureCalibrationSettings(const QJsonObject configurationSettings);
|
||||
QJsonObject configurationSettings();
|
||||
controller::Pose addOffsetToPuckPose(int joint) const;
|
||||
|
@ -106,7 +107,7 @@ private:
|
|||
void calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration);
|
||||
void calibrateFromHandController(const controller::InputCalibrationData& inputCalibrationData);
|
||||
void calibrateFromUI(const controller::InputCalibrationData& inputCalibrationData);
|
||||
void emitCalibrationStatus(const bool success);
|
||||
void emitCalibrationStatus();
|
||||
void calibrateNextFrame();
|
||||
|
||||
|
||||
|
@ -139,7 +140,7 @@ private:
|
|||
FeetAndHips,
|
||||
FeetHipsAndChest,
|
||||
FeetHipsAndShoulders,
|
||||
FeetHipsChestAndShoulders,
|
||||
FeetHipsChestAndShoulders
|
||||
};
|
||||
|
||||
enum class HeadConfig {
|
||||
|
|
|
@ -20,7 +20,9 @@ var blastShareText = "Blast to my Connections",
|
|||
hifiShareText = "Share to Snaps Feed",
|
||||
hifiAlreadySharedText = "Already Shared to Snaps Feed",
|
||||
facebookShareText = "Share to Facebook",
|
||||
twitterShareText = "Share to Twitter";
|
||||
twitterShareText = "Share to Twitter",
|
||||
shareButtonLabelTextActive = "SHARE:",
|
||||
shareButtonLabelTextInactive = "SHARE";
|
||||
|
||||
function fileExtensionMatches(filePath, extension) {
|
||||
return filePath.split('.').pop().toLowerCase() === extension;
|
||||
|
@ -138,6 +140,8 @@ function selectImageToShare(selectedID, isSelected) {
|
|||
var imageContainer = document.getElementById(selectedID),
|
||||
image = document.getElementById(selectedID + 'img'),
|
||||
shareBar = document.getElementById(selectedID + "shareBar"),
|
||||
showShareButtonsDots = document.getElementById(selectedID + "showShareButtonsDots"),
|
||||
showShareButtonsLabel = document.getElementById(selectedID + "showShareButtonsLabel"),
|
||||
shareButtonsDiv = document.getElementById(selectedID + "shareButtonsDiv"),
|
||||
shareBarHelp = document.getElementById(selectedID + "shareBarHelp"),
|
||||
showShareButtonsButtonDiv = document.getElementById(selectedID + "showShareButtonsButtonDiv"),
|
||||
|
@ -156,6 +160,9 @@ function selectImageToShare(selectedID, isSelected) {
|
|||
shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.45)";
|
||||
shareBar.style.pointerEvents = "initial";
|
||||
|
||||
showShareButtonsDots.style.visibility = "hidden";
|
||||
showShareButtonsLabel.innerHTML = shareButtonLabelTextActive;
|
||||
|
||||
shareButtonsDiv.style.visibility = "visible";
|
||||
shareBarHelp.style.visibility = "visible";
|
||||
|
||||
|
@ -176,6 +183,9 @@ function selectImageToShare(selectedID, isSelected) {
|
|||
shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.0)";
|
||||
shareBar.style.pointerEvents = "none";
|
||||
|
||||
showShareButtonsDots.style.visibility = "visible";
|
||||
showShareButtonsLabel.innerHTML = shareButtonLabelTextInactive;
|
||||
|
||||
shareButtonsDiv.style.visibility = "hidden";
|
||||
shareBarHelp.style.visibility = "hidden";
|
||||
}
|
||||
|
@ -185,6 +195,7 @@ function createShareBar(parentID, isLoggedIn, canShare, isGif, blastButtonDisabl
|
|||
shareBarHelpID = parentID + "shareBarHelp",
|
||||
shareButtonsDivID = parentID + "shareButtonsDiv",
|
||||
showShareButtonsButtonDivID = parentID + "showShareButtonsButtonDiv",
|
||||
showShareButtonsDotsID = parentID + "showShareButtonsDots",
|
||||
showShareButtonsLabelID = parentID + "showShareButtonsLabel",
|
||||
blastToConnectionsButtonID = parentID + "blastToConnectionsButton",
|
||||
shareWithEveryoneButtonID = parentID + "shareWithEveryoneButton",
|
||||
|
@ -199,8 +210,8 @@ function createShareBar(parentID, isLoggedIn, canShare, isGif, blastButtonDisabl
|
|||
if (canShare) {
|
||||
shareBarInnerHTML = '<div class="shareControlsHelp" id="' + shareBarHelpID + '" style="visibility:hidden;' + ((canBlast && blastButtonDisabled || !canBlast && hifiButtonDisabled) ? "background-color:#000;opacity:0.5;" : "") + '"></div>' +
|
||||
'<div class="showShareButtonsButtonDiv inactive" id="' + showShareButtonsButtonDivID + '" onclick="selectImageToShare(' + parentID + ', true)">' +
|
||||
'<label id="' + showShareButtonsLabelID + '">SHARE</label>' +
|
||||
'<span class="showShareButtonDots">' +
|
||||
'<label id="' + showShareButtonsLabelID + '">' + shareButtonLabelTextInactive + '</label>' +
|
||||
'<span id="' + showShareButtonsDotsID + '" class="showShareButtonDots">' +
|
||||
'' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
@ -217,7 +228,7 @@ function createShareBar(parentID, isLoggedIn, canShare, isGif, blastButtonDisabl
|
|||
document.getElementById(parentID + 'img').onclick = function () { selectImageToShare(parentID, true); };
|
||||
} else {
|
||||
shareBarInnerHTML = '<div class="showShareButtonsButtonDiv inactive" id="' + showShareButtonsButtonDivID + '" onclick="selectImageToShare(' + parentID + ', true)">' +
|
||||
'<label id="' + showShareButtonsLabelID + '">SHARE</label>' +
|
||||
'<label id="' + showShareButtonsLabelID + '">' + shareButtonLabelTextInactive + '</label>' +
|
||||
'<span class="showShareButtonDots">' +
|
||||
'' +
|
||||
'</div>' +
|
||||
|
@ -230,7 +241,7 @@ function createShareBar(parentID, isLoggedIn, canShare, isGif, blastButtonDisabl
|
|||
}
|
||||
} else {
|
||||
shareBarInnerHTML = '<div class="showShareButtonsButtonDiv inactive" id="' + showShareButtonsButtonDivID + '" onclick="selectImageToShare(' + parentID + ', true)">' +
|
||||
'<label id="' + showShareButtonsLabelID + '">SHARE</label>' +
|
||||
'<label id="' + showShareButtonsLabelID + '">' + shareButtonLabelTextInactive + '</label>' +
|
||||
'<span class="showShareButtonDots">' +
|
||||
'' +
|
||||
'</div>' +
|
||||
|
|
|
@ -90,14 +90,16 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
|
|||
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
// start the nodeThread so its event loop is running
|
||||
nodeList->startThread();
|
||||
|
||||
// setup a timer for domain-server check ins
|
||||
QTimer* domainCheckInTimer = new QTimer(nodeList.data());
|
||||
connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
|
||||
domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||
|
||||
// start the nodeThread so its event loop is running
|
||||
// (must happen after the checkin timer is created with the nodelist as it's parent)
|
||||
nodeList->startThread();
|
||||
|
||||
const DomainHandler& domainHandler = nodeList->getDomainHandler();
|
||||
|
||||
connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&)));
|
||||
|
|
Loading…
Reference in a new issue