mirror of
https://github.com/overte-org/overte.git
synced 2025-04-30 00:42:46 +02:00
MErging maybe finally ??????
This commit is contained in:
commit
2ad6c2067b
34 changed files with 922 additions and 198 deletions
|
@ -27,6 +27,10 @@
|
||||||
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
||||||
QCoreApplication(argc, argv)
|
QCoreApplication(argc, argv)
|
||||||
{
|
{
|
||||||
|
// to work around the Qt constant wireless scanning, set the env for polling interval very high
|
||||||
|
const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT_MAX).toLocal8Bit();
|
||||||
|
qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT);
|
||||||
|
|
||||||
# ifndef WIN32
|
# ifndef WIN32
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -62,6 +62,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
|
|
||||||
LogUtils::init();
|
LogUtils::init();
|
||||||
Setting::init();
|
Setting::init();
|
||||||
|
|
||||||
|
// to work around the Qt constant wireless scanning, set the env for polling interval very high
|
||||||
|
const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT_MAX).toLocal8Bit();
|
||||||
|
qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT);
|
||||||
|
|
||||||
connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit);
|
connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit);
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ Avatar = function() {
|
||||||
|
|
||||||
// only need to zero right leg IK chain and hips
|
// only need to zero right leg IK chain and hips
|
||||||
if (IKChain === "RightLeg" || joint === "Hips" ) {
|
if (IKChain === "RightLeg" || joint === "Hips" ) {
|
||||||
MyAvatar.setJointData(joint, Quat.fromPitchYawRollDegrees(0, 0, 0));
|
MyAvatar.setJointRotation(joint, Quat.fromPitchYawRollDegrees(0, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.calibration.hipsToFeet = MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightToeBase").y;
|
this.calibration.hipsToFeet = MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightToeBase").y;
|
||||||
|
@ -112,16 +112,16 @@ Avatar = function() {
|
||||||
this.poseFingers = function() {
|
this.poseFingers = function() {
|
||||||
for (knuckle in walkAssets.animationReference.leftHand) {
|
for (knuckle in walkAssets.animationReference.leftHand) {
|
||||||
if (walkAssets.animationReference.leftHand[knuckle].IKChain === "LeftHandThumb") {
|
if (walkAssets.animationReference.leftHand[knuckle].IKChain === "LeftHandThumb") {
|
||||||
MyAvatar.setJointData(knuckle, Quat.fromPitchYawRollDegrees(0, 0, -4));
|
MyAvatar.setJointRotation(knuckle, Quat.fromPitchYawRollDegrees(0, 0, -4));
|
||||||
} else {
|
} else {
|
||||||
MyAvatar.setJointData(knuckle, Quat.fromPitchYawRollDegrees(16, 0, 5));
|
MyAvatar.setJointRotation(knuckle, Quat.fromPitchYawRollDegrees(16, 0, 5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (knuckle in walkAssets.animationReference.rightHand) {
|
for (knuckle in walkAssets.animationReference.rightHand) {
|
||||||
if (walkAssets.animationReference.rightHand[knuckle].IKChain === "RightHandThumb") {
|
if (walkAssets.animationReference.rightHand[knuckle].IKChain === "RightHandThumb") {
|
||||||
MyAvatar.setJointData(knuckle, Quat.fromPitchYawRollDegrees(0, 0, 4));
|
MyAvatar.setJointRotation(knuckle, Quat.fromPitchYawRollDegrees(0, 0, 4));
|
||||||
} else {
|
} else {
|
||||||
MyAvatar.setJointData(knuckle, Quat.fromPitchYawRollDegrees(16, 0, -5));
|
MyAvatar.setJointRotation(knuckle, Quat.fromPitchYawRollDegrees(16, 0, -5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -449,6 +449,6 @@ function renderMotion() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply rotations
|
// apply rotations
|
||||||
MyAvatar.setJointData(jointName, Quat.fromVec3Degrees(jointRotations));
|
MyAvatar.setJointRotation(jointName, Quat.fromVec3Degrees(jointRotations));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -373,7 +373,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
thread()->setObjectName("Main Thread");
|
thread()->setObjectName("Main Thread");
|
||||||
|
|
||||||
setInstance(this);
|
setInstance(this);
|
||||||
|
|
||||||
|
// to work around the Qt constant wireless scanning, set the env for polling interval very high
|
||||||
|
const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT_MAX).toLocal8Bit();
|
||||||
|
qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT);
|
||||||
|
|
||||||
_entityClipboard->createRootElement();
|
_entityClipboard->createRootElement();
|
||||||
|
|
||||||
_pluginContainer = new PluginContainerProxy();
|
_pluginContainer = new PluginContainerProxy();
|
||||||
|
@ -1109,13 +1113,10 @@ void Application::paintGL() {
|
||||||
}
|
}
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
if (isHMDMode()) {
|
if (isHMDMode()) {
|
||||||
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation() * hmdRotation);
|
_myCamera.setRotation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
||||||
// Ignore MenuOption::CenterPlayerInView in HMD view
|
auto worldBoomOffset = myAvatar->getOrientation() * (myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
_myCamera.setPosition(extractTranslation(hmdWorldMat) + worldBoomOffset);
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
|
||||||
+ myAvatar->getOrientation()
|
|
||||||
* (myAvatar->getScale() * myAvatar->getBoomLength() * glm::vec3(0.0f, 0.0f, 1.0f) + hmdOffset));
|
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setRotation(myAvatar->getHead()->getOrientation());
|
_myCamera.setRotation(myAvatar->getHead()->getOrientation());
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
|
#include "assets/ATPAssetMigrator.h"
|
||||||
#include "audio/AudioScope.h"
|
#include "audio/AudioScope.h"
|
||||||
#include "avatar/AvatarManager.h"
|
#include "avatar/AvatarManager.h"
|
||||||
#include "devices/DdeFaceTracker.h"
|
#include "devices/DdeFaceTracker.h"
|
||||||
|
@ -354,7 +355,7 @@ Menu::Menu() {
|
||||||
MenuWrapper* assetDeveloperMenu = developerMenu->addMenu("Assets");
|
MenuWrapper* assetDeveloperMenu = developerMenu->addMenu("Assets");
|
||||||
|
|
||||||
auto& assetDialogFactory = AssetUploadDialogFactory::getInstance();
|
auto& assetDialogFactory = AssetUploadDialogFactory::getInstance();
|
||||||
assetDialogFactory.setParent(this);
|
assetDialogFactory.setDialogParent(this);
|
||||||
|
|
||||||
QAction* assetUpload = addActionToQMenuAndActionHash(assetDeveloperMenu,
|
QAction* assetUpload = addActionToQMenuAndActionHash(assetDeveloperMenu,
|
||||||
MenuOption::UploadAsset,
|
MenuOption::UploadAsset,
|
||||||
|
@ -365,6 +366,13 @@ Menu::Menu() {
|
||||||
// disable the asset upload action by default - it gets enabled only if asset server becomes present
|
// disable the asset upload action by default - it gets enabled only if asset server becomes present
|
||||||
assetUpload->setEnabled(false);
|
assetUpload->setEnabled(false);
|
||||||
|
|
||||||
|
auto& atpMigrator = ATPAssetMigrator::getInstance();
|
||||||
|
atpMigrator.setDialogParent(this);
|
||||||
|
|
||||||
|
QAction* assetMigration = addActionToQMenuAndActionHash(assetDeveloperMenu, MenuOption::AssetMigration,
|
||||||
|
0, &atpMigrator,
|
||||||
|
SLOT(loadEntityServerFile()));
|
||||||
|
|
||||||
MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar");
|
MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar");
|
||||||
|
|
||||||
MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking");
|
MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking");
|
||||||
|
|
|
@ -135,6 +135,7 @@ namespace MenuOption {
|
||||||
const QString AnimDebugDrawAnimPose = "Debug Draw Animation";
|
const QString AnimDebugDrawAnimPose = "Debug Draw Animation";
|
||||||
const QString AnimDebugDrawBindPose = "Debug Draw Bind Pose";
|
const QString AnimDebugDrawBindPose = "Debug Draw Bind Pose";
|
||||||
const QString Antialiasing = "Antialiasing";
|
const QString Antialiasing = "Antialiasing";
|
||||||
|
const QString AssetMigration = "ATP Asset Migration";
|
||||||
const QString Atmosphere = "Atmosphere";
|
const QString Atmosphere = "Atmosphere";
|
||||||
const QString Attachments = "Attachments...";
|
const QString Attachments = "Attachments...";
|
||||||
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
||||||
|
|
273
interface/src/assets/ATPAssetMigrator.cpp
Normal file
273
interface/src/assets/ATPAssetMigrator.cpp
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
//
|
||||||
|
// ATPAssetMigrator.cpp
|
||||||
|
// interface/src/assets
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 2015-10-12.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ATPAssetMigrator.h"
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QJsonDocument>
|
||||||
|
#include <QtCore/QJsonObject>
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
#include <QtCore/QTemporaryFile>
|
||||||
|
#include <QtWidgets/QFileDialog>
|
||||||
|
#include <QtWidgets/QMessageBox>
|
||||||
|
|
||||||
|
#include <Gzip.h>
|
||||||
|
|
||||||
|
#include <AssetClient.h>
|
||||||
|
#include <AssetUpload.h>
|
||||||
|
#include <ResourceManager.h>
|
||||||
|
|
||||||
|
#include "../ui/AssetUploadDialogFactory.h"
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(asset_migrator);
|
||||||
|
Q_LOGGING_CATEGORY(asset_migrator, "hf.asset_migrator");
|
||||||
|
|
||||||
|
ATPAssetMigrator& ATPAssetMigrator::getInstance() {
|
||||||
|
static ATPAssetMigrator instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const QString ENTITIES_OBJECT_KEY = "Entities";
|
||||||
|
static const QString MODEL_URL_KEY = "modelURL";
|
||||||
|
static const QString MESSAGE_BOX_TITLE = "ATP Asset Migration";
|
||||||
|
|
||||||
|
void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
|
auto filename = QFileDialog::getOpenFileName(_dialogParent, "Select an entity-server content file to migrate",
|
||||||
|
QString(), QString("Entity-Server Content (*.gz)"));
|
||||||
|
|
||||||
|
if (!filename.isEmpty()) {
|
||||||
|
qCDebug(asset_migrator) << "Selected filename for ATP asset migration: " << filename;
|
||||||
|
|
||||||
|
static const QString MIGRATION_CONFIRMATION_TEXT {
|
||||||
|
"The ATP Asset Migration process will scan the selected entity-server file, upload discovered resources to the"\
|
||||||
|
" current asset-server and then save a new entity-server file with the ATP URLs.\n\nAre you ready to"\
|
||||||
|
" continue?\n\nMake sure you are connected to the right domain."
|
||||||
|
};
|
||||||
|
|
||||||
|
auto button = QMessageBox::question(_dialogParent, MESSAGE_BOX_TITLE, MIGRATION_CONFIRMATION_TEXT,
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
|
|
||||||
|
if (button == QMessageBox::No) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to open the file at the given filename
|
||||||
|
QFile modelsFile { filename };
|
||||||
|
|
||||||
|
if (modelsFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QByteArray compressedJsonData = modelsFile.readAll();
|
||||||
|
QByteArray jsonData;
|
||||||
|
|
||||||
|
if (!gunzip(compressedJsonData, jsonData)) {
|
||||||
|
QMessageBox::warning(_dialogParent, "Error", "The file at" + filename + "was not in gzip format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument modelsJSON = QJsonDocument::fromJson(jsonData);
|
||||||
|
_entitiesArray = modelsJSON.object()["Entities"].toArray();
|
||||||
|
|
||||||
|
for (auto jsonValue : _entitiesArray) {
|
||||||
|
QJsonObject entityObject = jsonValue.toObject();
|
||||||
|
QString modelURLString = entityObject.value(MODEL_URL_KEY).toString();
|
||||||
|
|
||||||
|
if (!modelURLString.isEmpty()) {
|
||||||
|
QUrl modelURL = QUrl(modelURLString);
|
||||||
|
|
||||||
|
if (!_ignoredUrls.contains(modelURL)
|
||||||
|
&& (modelURL.scheme() == URL_SCHEME_HTTP || modelURL.scheme() == URL_SCHEME_HTTPS
|
||||||
|
|| modelURL.scheme() == URL_SCHEME_FILE || modelURL.scheme() == URL_SCHEME_FTP)) {
|
||||||
|
|
||||||
|
if (_pendingReplacements.contains(modelURL)) {
|
||||||
|
// we already have a request out for this asset, just store the QJsonValueRef
|
||||||
|
// so we can do the hash replacement when the request comes back
|
||||||
|
_pendingReplacements.insert(modelURL, jsonValue);
|
||||||
|
} else if (_uploadedAssets.contains(modelURL)) {
|
||||||
|
// we already have a hash for this asset
|
||||||
|
// so just do the replacement immediately
|
||||||
|
entityObject[MODEL_URL_KEY] = _uploadedAssets.value(modelURL).toString();
|
||||||
|
jsonValue = entityObject;
|
||||||
|
} else if (wantsToMigrateResource(modelURL)) {
|
||||||
|
auto request = ResourceManager::createResourceRequest(this, modelURL);
|
||||||
|
|
||||||
|
if (request) {
|
||||||
|
qCDebug(asset_migrator) << "Requesting" << modelURL << "for ATP asset migration";
|
||||||
|
|
||||||
|
// add this combination of QUrl and QJsonValueRef to our multi hash so we can change the URL
|
||||||
|
// to an ATP one once ready
|
||||||
|
_pendingReplacements.insert(modelURL, jsonValue);
|
||||||
|
|
||||||
|
connect(request, &ResourceRequest::finished, this, [=]() {
|
||||||
|
if (request->getResult() == ResourceRequest::Success) {
|
||||||
|
migrateResource(request);
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(_dialogParent, "Error",
|
||||||
|
QString("Could not retrieve asset at %1").arg(modelURL.toString()));
|
||||||
|
}
|
||||||
|
request->deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
|
request->send();
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(_dialogParent, "Error",
|
||||||
|
QString("Could not create request for asset at %1").arg(modelURL.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_ignoredUrls.insert(modelURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_doneReading = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(_dialogParent, "Error",
|
||||||
|
"There was a problem loading that entity-server file for ATP asset migration. Please try again");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATPAssetMigrator::migrateResource(ResourceRequest* request) {
|
||||||
|
// use an asset client to upload the asset
|
||||||
|
auto assetClient = DependencyManager::get<AssetClient>();
|
||||||
|
|
||||||
|
QFileInfo assetInfo { request->getUrl().fileName() };
|
||||||
|
|
||||||
|
auto upload = assetClient->createUpload(request->getData(), assetInfo.completeSuffix());
|
||||||
|
|
||||||
|
if (upload) {
|
||||||
|
// add this URL to our hash of AssetUpload to original URL
|
||||||
|
_originalURLs.insert(upload, request->getUrl());
|
||||||
|
|
||||||
|
qCDebug(asset_migrator) << "Starting upload of asset from" << request->getUrl();
|
||||||
|
|
||||||
|
// connect to the finished signal so we know when the AssetUpload is done
|
||||||
|
QObject::connect(upload, &AssetUpload::finished, this, &ATPAssetMigrator::assetUploadFinished);
|
||||||
|
|
||||||
|
// start the upload now
|
||||||
|
upload->start();
|
||||||
|
} else {
|
||||||
|
// show a QMessageBox to say that there is no local asset server
|
||||||
|
QString messageBoxText = QString("Could not upload \n\n%1\n\nbecause you are currently not connected" \
|
||||||
|
" to a local asset-server.").arg(assetInfo.fileName());
|
||||||
|
|
||||||
|
QMessageBox::information(_dialogParent, "Failed to Upload", messageBoxText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATPAssetMigrator::assetUploadFinished(AssetUpload *upload, const QString& hash) {
|
||||||
|
if (upload->getError() == AssetUpload::NoError) {
|
||||||
|
|
||||||
|
const auto& modelURL = _originalURLs[upload];
|
||||||
|
|
||||||
|
// successfully uploaded asset - make any required replacements found in the pending replacements
|
||||||
|
auto values = _pendingReplacements.values(modelURL);
|
||||||
|
|
||||||
|
|
||||||
|
QString atpURL = getATPUrl(hash, upload->getExtension()).toString();
|
||||||
|
|
||||||
|
for (auto value : values) {
|
||||||
|
// replace the modelURL in this QJsonValueRef with the hash
|
||||||
|
QJsonObject valueObject = value.toObject();
|
||||||
|
valueObject[MODEL_URL_KEY] = atpURL;
|
||||||
|
value = valueObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add this URL to our list of uploaded assets
|
||||||
|
_uploadedAssets.insert(modelURL, atpURL);
|
||||||
|
|
||||||
|
// pull the replaced models from _pendingReplacements
|
||||||
|
_pendingReplacements.remove(modelURL);
|
||||||
|
|
||||||
|
// are we out of pending replacements? if so it is time to save the entity-server file
|
||||||
|
if (_doneReading && _pendingReplacements.empty()) {
|
||||||
|
saveEntityServerFile();
|
||||||
|
|
||||||
|
// reset after the attempted save, success or fail
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AssetUploadDialogFactory::showErrorDialog(upload, _dialogParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
upload->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ATPAssetMigrator::wantsToMigrateResource(const QUrl& url) {
|
||||||
|
static bool hasAskedForCompleteMigration { false };
|
||||||
|
static bool wantsCompleteMigration { false };
|
||||||
|
|
||||||
|
if (!hasAskedForCompleteMigration) {
|
||||||
|
// this is the first resource migration - ask the user if they just want to migrate everything
|
||||||
|
static const QString COMPLETE_MIGRATION_TEXT { "Do you want to migrate all assets found in this entity-server file?\n\n"\
|
||||||
|
"Select \"Yes\" to upload all discovered assets to the current asset-server immediately.\n\n"\
|
||||||
|
"Select \"No\" to be prompted for each discovered asset."
|
||||||
|
};
|
||||||
|
|
||||||
|
auto button = QMessageBox::question(_dialogParent, MESSAGE_BOX_TITLE, COMPLETE_MIGRATION_TEXT,
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
|
|
||||||
|
if (button == QMessageBox::Yes) {
|
||||||
|
wantsCompleteMigration = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAskedForCompleteMigration = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantsCompleteMigration) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// present a dialog asking the user if they want to migrate this specific resource
|
||||||
|
auto button = QMessageBox::question(_dialogParent, MESSAGE_BOX_TITLE,
|
||||||
|
"Would you like to migrate the following resource?\n" + url.toString(),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
|
return button == QMessageBox::Yes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATPAssetMigrator::saveEntityServerFile() {
|
||||||
|
// show a dialog to ask the user where they want to save the file
|
||||||
|
QString saveName = QFileDialog::getSaveFileName(_dialogParent, "Save Migrated Entities File");
|
||||||
|
|
||||||
|
QFile saveFile { saveName };
|
||||||
|
|
||||||
|
if (saveFile.open(QIODevice::WriteOnly)) {
|
||||||
|
QJsonObject rootObject;
|
||||||
|
rootObject[ENTITIES_OBJECT_KEY] = _entitiesArray;
|
||||||
|
|
||||||
|
QJsonDocument newDocument { rootObject };
|
||||||
|
QByteArray jsonDataForFile;
|
||||||
|
|
||||||
|
if (gzip(newDocument.toJson(), jsonDataForFile, -1)) {
|
||||||
|
|
||||||
|
saveFile.write(jsonDataForFile);
|
||||||
|
saveFile.close();
|
||||||
|
|
||||||
|
QMessageBox::information(_dialogParent, "Success",
|
||||||
|
QString("Your new entities file has been saved at %1").arg(saveName));
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(_dialogParent, "Error", "Could not gzip JSON data for new entities file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(_dialogParent, "Error",
|
||||||
|
QString("Could not open file at %1 to write new entities file to.").arg(saveName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATPAssetMigrator::reset() {
|
||||||
|
_entitiesArray = QJsonArray();
|
||||||
|
_doneReading = false;
|
||||||
|
_pendingReplacements.clear();
|
||||||
|
_uploadedAssets.clear();
|
||||||
|
_originalURLs.clear();
|
||||||
|
_ignoredUrls.clear();
|
||||||
|
}
|
55
interface/src/assets/ATPAssetMigrator.h
Normal file
55
interface/src/assets/ATPAssetMigrator.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// ATPAssetMigrator.h
|
||||||
|
// interface/src/assets
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 2015-10-12.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef hifi_ATPAssetMigrator_h
|
||||||
|
#define hifi_ATPAssetMigrator_h
|
||||||
|
|
||||||
|
#include <QtCore/QJsonArray>
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QMultiHash>
|
||||||
|
#include <QtCore/QSet>
|
||||||
|
|
||||||
|
class AssetUpload;
|
||||||
|
class ResourceRequest;
|
||||||
|
|
||||||
|
class ATPAssetMigrator : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static ATPAssetMigrator& getInstance();
|
||||||
|
|
||||||
|
void setDialogParent(QWidget* dialogParent) { _dialogParent = dialogParent; }
|
||||||
|
public slots:
|
||||||
|
void loadEntityServerFile();
|
||||||
|
private slots:
|
||||||
|
void assetUploadFinished(AssetUpload* upload, const QString& hash);
|
||||||
|
private:
|
||||||
|
void migrateResource(ResourceRequest* request);
|
||||||
|
void saveEntityServerFile();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
bool wantsToMigrateResource(const QUrl& url);
|
||||||
|
|
||||||
|
QWidget* _dialogParent = nullptr;
|
||||||
|
QJsonArray _entitiesArray;
|
||||||
|
|
||||||
|
bool _doneReading { false };
|
||||||
|
|
||||||
|
QMultiHash<QUrl, QJsonValueRef> _pendingReplacements;
|
||||||
|
QHash<QUrl, QUrl> _uploadedAssets;
|
||||||
|
QHash<AssetUpload*, QUrl> _originalURLs;
|
||||||
|
QSet<QUrl> _ignoredUrls;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // hifi_ATPAssetMigrator_h
|
|
@ -326,6 +326,7 @@ static bool capsuleCheck(const glm::vec3& pos, float capsuleLen, float capsuleRa
|
||||||
// as it moves through the world.
|
// as it moves through the world.
|
||||||
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
|
|
||||||
|
// calc deltaTime
|
||||||
auto now = usecTimestampNow();
|
auto now = usecTimestampNow();
|
||||||
auto deltaUsecs = now - _lastUpdateFromHMDTime;
|
auto deltaUsecs = now - _lastUpdateFromHMDTime;
|
||||||
_lastUpdateFromHMDTime = now;
|
_lastUpdateFromHMDTime = now;
|
||||||
|
@ -340,21 +341,61 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
|
|
||||||
bool hmdIsAtRest = _hmdAtRestDetector.update(deltaTime, _hmdSensorPosition, _hmdSensorOrientation);
|
bool hmdIsAtRest = _hmdAtRestDetector.update(deltaTime, _hmdSensorPosition, _hmdSensorOrientation);
|
||||||
|
|
||||||
const float STRAIGHTENING_LEAN_DURATION = 0.5f; // seconds
|
// It can be more accurate/smooth to use velocity rather than position,
|
||||||
|
// but some modes (e.g., hmd standing) update position without updating velocity.
|
||||||
|
// So, let's create our own workingVelocity from the worldPosition...
|
||||||
|
glm::vec3 positionDelta = getPosition() - _lastPosition;
|
||||||
|
glm::vec3 workingVelocity = positionDelta / deltaTime;
|
||||||
|
_lastPosition = getPosition();
|
||||||
|
|
||||||
|
const float MOVE_ENTER_SPEED_THRESHOLD = 0.2f; // m/sec
|
||||||
|
const float MOVE_EXIT_SPEED_THRESHOLD = 0.07f; // m/sec
|
||||||
|
bool isMoving;
|
||||||
|
if (_lastIsMoving) {
|
||||||
|
isMoving = glm::length(workingVelocity) >= MOVE_EXIT_SPEED_THRESHOLD;
|
||||||
|
} else {
|
||||||
|
isMoving = glm::length(workingVelocity) > MOVE_ENTER_SPEED_THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool justStartedMoving = (_lastIsMoving != isMoving) && isMoving;
|
||||||
|
_lastIsMoving = isMoving;
|
||||||
|
|
||||||
|
if (shouldBeginStraighteningLean() || hmdIsAtRest || justStartedMoving) {
|
||||||
|
beginStraighteningLean();
|
||||||
|
}
|
||||||
|
|
||||||
|
processStraighteningLean(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::beginStraighteningLean() {
|
||||||
|
// begin homing toward derived body position.
|
||||||
|
if (!_straighteningLean) {
|
||||||
|
_straighteningLean = true;
|
||||||
|
_straighteningLeanAlpha = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::shouldBeginStraighteningLean() const {
|
||||||
// define a vertical capsule
|
// define a vertical capsule
|
||||||
const float STRAIGHTENING_LEAN_CAPSULE_RADIUS = 0.2f; // meters
|
const float STRAIGHTENING_LEAN_CAPSULE_RADIUS = 0.2f; // meters
|
||||||
const float STRAIGHTENING_LEAN_CAPSULE_LENGTH = 0.05f; // length of the cylinder part of the capsule in meters.
|
const float STRAIGHTENING_LEAN_CAPSULE_LENGTH = 0.05f; // length of the cylinder part of the capsule in meters.
|
||||||
|
|
||||||
|
// detect if the derived body position is outside of a capsule around the _bodySensorMatrix
|
||||||
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
||||||
glm::vec3 diff = extractTranslation(newBodySensorMatrix) - extractTranslation(_bodySensorMatrix);
|
glm::vec3 diff = extractTranslation(newBodySensorMatrix) - extractTranslation(_bodySensorMatrix);
|
||||||
if (!_straighteningLean && (capsuleCheck(diff, STRAIGHTENING_LEAN_CAPSULE_LENGTH, STRAIGHTENING_LEAN_CAPSULE_RADIUS) || hmdIsAtRest)) {
|
bool isBodyPosOutsideCapsule = capsuleCheck(diff, STRAIGHTENING_LEAN_CAPSULE_LENGTH, STRAIGHTENING_LEAN_CAPSULE_RADIUS);
|
||||||
|
|
||||||
// begin homing toward derived body position.
|
if (isBodyPosOutsideCapsule) {
|
||||||
_straighteningLean = true;
|
return true;
|
||||||
_straighteningLeanAlpha = 0.0f;
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (_straighteningLean) {
|
void MyAvatar::processStraighteningLean(float deltaTime) {
|
||||||
|
if (_straighteningLean) {
|
||||||
|
|
||||||
|
const float STRAIGHTENING_LEAN_DURATION = 0.5f; // seconds
|
||||||
|
|
||||||
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
||||||
auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix;
|
auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix;
|
||||||
|
@ -1160,32 +1201,41 @@ void MyAvatar::setJointTranslations(QVector<glm::vec3> jointTranslations) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setJointData(int index, const glm::quat& rotation, const glm::vec3& translation) {
|
void MyAvatar::setJointData(int index, const glm::quat& rotation, const glm::vec3& translation) {
|
||||||
if (QThread::currentThread() == thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
// HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority
|
QMetaObject::invokeMethod(this, "setJointData", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation),
|
||||||
_rig->setJointState(index, true, rotation, translation, SCRIPT_PRIORITY);
|
Q_ARG(const glm::vec3&, translation));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority
|
||||||
|
_rig->setJointState(index, true, rotation, translation, SCRIPT_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setJointRotation(int index, const glm::quat& rotation) {
|
void MyAvatar::setJointRotation(int index, const glm::quat& rotation) {
|
||||||
if (QThread::currentThread() == thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
// HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority
|
QMetaObject::invokeMethod(this, "setJointRotation", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation));
|
||||||
_rig->setJointRotation(index, true, rotation, SCRIPT_PRIORITY);
|
return;
|
||||||
}
|
}
|
||||||
|
// HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority
|
||||||
|
_rig->setJointRotation(index, true, rotation, SCRIPT_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setJointTranslation(int index, const glm::vec3& translation) {
|
void MyAvatar::setJointTranslation(int index, const glm::vec3& translation) {
|
||||||
if (QThread::currentThread() == thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
// HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority
|
QMetaObject::invokeMethod(this, "setJointTranslation", Q_ARG(int, index), Q_ARG(const glm::vec3&, translation));
|
||||||
_rig->setJointTranslation(index, true, translation, SCRIPT_PRIORITY);
|
return;
|
||||||
}
|
}
|
||||||
|
// HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority
|
||||||
|
_rig->setJointTranslation(index, true, translation, SCRIPT_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::clearJointData(int index) {
|
void MyAvatar::clearJointData(int index) {
|
||||||
if (QThread::currentThread() == thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
// HACK: ATM only JS scripts call clearJointData() on MyAvatar so we hardcode the priority
|
QMetaObject::invokeMethod(this, "clearJointData", Q_ARG(int, index));
|
||||||
_rig->setJointState(index, false, glm::quat(), glm::vec3(), 0.0f);
|
return;
|
||||||
_rig->clearJointAnimationPriority(index);
|
|
||||||
}
|
}
|
||||||
|
// HACK: ATM only JS scripts call clearJointData() on MyAvatar so we hardcode the priority
|
||||||
|
_rig->setJointState(index, false, glm::quat(), glm::vec3(), 0.0f);
|
||||||
|
_rig->clearJointAnimationPriority(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::clearJointsData() {
|
void MyAvatar::clearJointsData() {
|
||||||
|
|
|
@ -271,6 +271,10 @@ private:
|
||||||
const RecorderPointer getRecorder() const { return _recorder; }
|
const RecorderPointer getRecorder() const { return _recorder; }
|
||||||
const PlayerPointer getPlayer() const { return _player; }
|
const PlayerPointer getPlayer() const { return _player; }
|
||||||
|
|
||||||
|
void beginStraighteningLean();
|
||||||
|
bool shouldBeginStraighteningLean() const;
|
||||||
|
void processStraighteningLean(float deltaTime);
|
||||||
|
|
||||||
bool cameraInsideHead() const;
|
bool cameraInsideHead() const;
|
||||||
|
|
||||||
// These are made private for MyAvatar so that you will use the "use" methods instead
|
// These are made private for MyAvatar so that you will use the "use" methods instead
|
||||||
|
@ -366,6 +370,8 @@ private:
|
||||||
|
|
||||||
quint64 _lastUpdateFromHMDTime = usecTimestampNow();
|
quint64 _lastUpdateFromHMDTime = usecTimestampNow();
|
||||||
AtRestDetector _hmdAtRestDetector;
|
AtRestDetector _hmdAtRestDetector;
|
||||||
|
glm::vec3 _lastPosition;
|
||||||
|
bool _lastIsMoving = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
||||||
|
|
|
@ -30,7 +30,7 @@ AssetUploadDialogFactory& AssetUploadDialogFactory::getInstance() {
|
||||||
return staticInstance;
|
return staticInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QString PERMISSION_DENIED_ERROR = "You do not have permission to upload content to this asset-server.";
|
|
||||||
|
|
||||||
void AssetUploadDialogFactory::showDialog() {
|
void AssetUploadDialogFactory::showDialog() {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
@ -60,7 +60,7 @@ void AssetUploadDialogFactory::showDialog() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we don't have permission to upload to asset server in this domain - show the permission denied error
|
// we don't have permission to upload to asset server in this domain - show the permission denied error
|
||||||
showErrorDialog(QString(), PERMISSION_DENIED_ERROR);
|
showErrorDialog(nullptr, _dialogParent, AssetUpload::PERMISSION_DENIED_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -118,42 +118,33 @@ void AssetUploadDialogFactory::handleUploadFinished(AssetUpload* upload, const Q
|
||||||
// show the new dialog
|
// show the new dialog
|
||||||
hashCopyDialog->show();
|
hashCopyDialog->show();
|
||||||
} else {
|
} else {
|
||||||
// figure out the right error message for the message box
|
|
||||||
QString additionalError;
|
|
||||||
|
|
||||||
switch (upload->getError()) {
|
|
||||||
case AssetUpload::PermissionDenied:
|
|
||||||
additionalError = PERMISSION_DENIED_ERROR;
|
|
||||||
break;
|
|
||||||
case AssetUpload::TooLarge:
|
|
||||||
additionalError = "The uploaded content was too large and could not be stored in the asset-server.";
|
|
||||||
break;
|
|
||||||
case AssetUpload::FileOpenError:
|
|
||||||
additionalError = "The file could not be opened. Please check your permissions and try again.";
|
|
||||||
break;
|
|
||||||
case AssetUpload::NetworkError:
|
|
||||||
additionalError = "The file could not be opened. Please check your network connectivity.";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// not handled, do not show a message box
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// display a message box with the error
|
// display a message box with the error
|
||||||
showErrorDialog(QFileInfo(upload->getFilename()).fileName(), additionalError);
|
showErrorDialog(upload, _dialogParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
upload->deleteLater();
|
upload->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUploadDialogFactory::showErrorDialog(const QString& filename, const QString& additionalError) {
|
void AssetUploadDialogFactory::showErrorDialog(AssetUpload* upload, QWidget* dialogParent, const QString& overrideMessage) {
|
||||||
QString errorMessage;
|
QString filename;
|
||||||
|
|
||||||
if (!filename.isEmpty()) {
|
if (upload) {
|
||||||
errorMessage += QString("Failed to upload %1.\n\n").arg(filename);
|
filename = QFileInfo { upload->getFilename() }.fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage += additionalError;
|
QString errorMessage = overrideMessage;
|
||||||
|
|
||||||
QMessageBox::warning(_dialogParent, "Failed Upload", errorMessage);
|
if (errorMessage.isEmpty() && upload) {
|
||||||
|
errorMessage = upload->getErrorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString dialogMessage;
|
||||||
|
|
||||||
|
if (upload) {
|
||||||
|
dialogMessage += QString("Failed to upload %1.\n\n").arg(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogMessage += errorMessage;
|
||||||
|
|
||||||
|
QMessageBox::warning(dialogParent, "Failed Upload", dialogMessage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
AssetUploadDialogFactory& operator=(const AssetUploadDialogFactory& rhs) = delete;
|
AssetUploadDialogFactory& operator=(const AssetUploadDialogFactory& rhs) = delete;
|
||||||
|
|
||||||
static AssetUploadDialogFactory& getInstance();
|
static AssetUploadDialogFactory& getInstance();
|
||||||
|
static void showErrorDialog(AssetUpload* upload, QWidget* dialogParent, const QString& overrideMessage = QString());
|
||||||
|
|
||||||
void setDialogParent(QWidget* dialogParent) { _dialogParent = dialogParent; }
|
void setDialogParent(QWidget* dialogParent) { _dialogParent = dialogParent; }
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ public slots:
|
||||||
private:
|
private:
|
||||||
AssetUploadDialogFactory() = default;
|
AssetUploadDialogFactory() = default;
|
||||||
|
|
||||||
void showErrorDialog(const QString& filename, const QString& additionalError);
|
|
||||||
|
|
||||||
QWidget* _dialogParent { nullptr };
|
QWidget* _dialogParent { nullptr };
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,7 +93,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointe
|
||||||
const float dt = 0.0f;
|
const float dt = 0.0f;
|
||||||
Triggers triggers;
|
Triggers triggers;
|
||||||
_nextPoses = nextStateNode->evaluate(animVars, dt, triggers);
|
_nextPoses = nextStateNode->evaluate(animVars, dt, triggers);
|
||||||
#if WANT_DEBUGa
|
#if WANT_DEBUG
|
||||||
qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID() << "duration =" << duration << "targetFrame =" << desiredState->_interpTarget;
|
qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID() << "duration =" << duration << "targetFrame =" << desiredState->_interpTarget;
|
||||||
#endif
|
#endif
|
||||||
_currentState = desiredState;
|
_currentState = desiredState;
|
||||||
|
|
|
@ -437,16 +437,6 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
static float t = 0.0f;
|
static float t = 0.0f;
|
||||||
_animVars.set("sine", static_cast<float>(0.5 * sin(t) + 0.5));
|
_animVars.set("sine", static_cast<float>(0.5 * sin(t) + 0.5));
|
||||||
|
|
||||||
// default anim vars to notMoving and notTurning
|
|
||||||
_animVars.set("isMovingForward", false);
|
|
||||||
_animVars.set("isMovingBackward", false);
|
|
||||||
_animVars.set("isMovingLeft", false);
|
|
||||||
_animVars.set("isMovingRight", false);
|
|
||||||
_animVars.set("isNotMoving", true);
|
|
||||||
_animVars.set("isTurningLeft", false);
|
|
||||||
_animVars.set("isTurningRight", false);
|
|
||||||
_animVars.set("isNotTurning", true);
|
|
||||||
|
|
||||||
const float ANIM_WALK_SPEED = 1.4f; // m/s
|
const float ANIM_WALK_SPEED = 1.4f; // m/s
|
||||||
_animVars.set("walkTimeScale", glm::clamp(0.5f, 2.0f, glm::length(localVel) / ANIM_WALK_SPEED));
|
_animVars.set("walkTimeScale", glm::clamp(0.5f, 2.0f, glm::length(localVel) / ANIM_WALK_SPEED));
|
||||||
|
|
||||||
|
@ -470,47 +460,102 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glm::length(localVel) > moveThresh) {
|
if (glm::length(localVel) > moveThresh) {
|
||||||
if (fabsf(forwardSpeed) > 0.5f * fabsf(lateralSpeed)) {
|
if (_desiredState != RigRole::Move) {
|
||||||
if (forwardSpeed > 0.0f) {
|
_desiredStateAge = 0.0f;
|
||||||
// forward
|
|
||||||
_animVars.set("isMovingForward", true);
|
|
||||||
_animVars.set("isNotMoving", false);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// backward
|
|
||||||
_animVars.set("isMovingBackward", true);
|
|
||||||
_animVars.set("isNotMoving", false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (lateralSpeed > 0.0f) {
|
|
||||||
// right
|
|
||||||
_animVars.set("isMovingRight", true);
|
|
||||||
_animVars.set("isNotMoving", false);
|
|
||||||
} else {
|
|
||||||
// left
|
|
||||||
_animVars.set("isMovingLeft", true);
|
|
||||||
_animVars.set("isNotMoving", false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_state = RigRole::Move;
|
_desiredState = RigRole::Move;
|
||||||
} else {
|
} else {
|
||||||
if (fabsf(turningSpeed) > turnThresh) {
|
if (fabsf(turningSpeed) > turnThresh) {
|
||||||
if (turningSpeed > 0.0f) {
|
if (_desiredState != RigRole::Turn) {
|
||||||
// turning right
|
_desiredStateAge = 0.0f;
|
||||||
_animVars.set("isTurningRight", true);
|
|
||||||
_animVars.set("isNotTurning", false);
|
|
||||||
} else {
|
|
||||||
// turning left
|
|
||||||
_animVars.set("isTurningLeft", true);
|
|
||||||
_animVars.set("isNotTurning", false);
|
|
||||||
}
|
}
|
||||||
_state = RigRole::Turn;
|
_desiredState = RigRole::Turn;
|
||||||
} else {
|
} else { // idle
|
||||||
// idle
|
if (_desiredState != RigRole::Idle) {
|
||||||
_state = RigRole::Idle;
|
_desiredStateAge = 0.0f;
|
||||||
|
}
|
||||||
|
_desiredState = RigRole::Idle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float STATE_CHANGE_HYSTERESIS_TIMER = 0.1f;
|
||||||
|
|
||||||
|
if ((_desiredStateAge >= STATE_CHANGE_HYSTERESIS_TIMER) && _desiredState != _state) {
|
||||||
|
_state = _desiredState;
|
||||||
|
_desiredStateAge = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
_desiredStateAge += deltaTime;
|
||||||
|
|
||||||
|
if (_state == RigRole::Move) {
|
||||||
|
if (glm::length(localVel) > MOVE_ENTER_SPEED_THRESHOLD) {
|
||||||
|
if (fabsf(forwardSpeed) > 0.5f * fabsf(lateralSpeed)) {
|
||||||
|
if (forwardSpeed > 0.0f) {
|
||||||
|
// forward
|
||||||
|
_animVars.set("isMovingForward", true);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isNotMoving", false);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// backward
|
||||||
|
_animVars.set("isMovingBackward", true);
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isNotMoving", false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lateralSpeed > 0.0f) {
|
||||||
|
// right
|
||||||
|
_animVars.set("isMovingRight", true);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isNotMoving", false);
|
||||||
|
} else {
|
||||||
|
// left
|
||||||
|
_animVars.set("isMovingLeft", true);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isNotMoving", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_animVars.set("isTurningLeft", false);
|
||||||
|
_animVars.set("isTurningRight", false);
|
||||||
|
_animVars.set("isNotTurning", true);
|
||||||
|
}
|
||||||
|
} else if (_state == RigRole::Turn) {
|
||||||
|
if (turningSpeed > 0.0f) {
|
||||||
|
// turning right
|
||||||
|
_animVars.set("isTurningRight", true);
|
||||||
|
_animVars.set("isTurningLeft", false);
|
||||||
|
_animVars.set("isNotTurning", false);
|
||||||
|
} else {
|
||||||
|
// turning left
|
||||||
|
_animVars.set("isTurningLeft", true);
|
||||||
|
_animVars.set("isTurningRight", false);
|
||||||
|
_animVars.set("isNotTurning", false);
|
||||||
|
}
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isNotMoving", true);
|
||||||
|
} else {
|
||||||
|
// default anim vars to notMoving and notTurning
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isNotMoving", true);
|
||||||
|
_animVars.set("isTurningLeft", false);
|
||||||
|
_animVars.set("isTurningRight", false);
|
||||||
|
_animVars.set("isNotTurning", true);
|
||||||
|
}
|
||||||
|
|
||||||
t += deltaTime;
|
t += deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,6 +236,8 @@ public:
|
||||||
Move
|
Move
|
||||||
};
|
};
|
||||||
RigRole _state = RigRole::Idle;
|
RigRole _state = RigRole::Idle;
|
||||||
|
RigRole _desiredState = RigRole::Idle;
|
||||||
|
float _desiredStateAge = 0.0f;
|
||||||
float _leftHandOverlayAlpha = 0.0f;
|
float _leftHandOverlayAlpha = 0.0f;
|
||||||
float _rightHandOverlayAlpha = 0.0f;
|
float _rightHandOverlayAlpha = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1032,13 +1032,30 @@ glm::vec3 AvatarData::getJointTranslation(const QString& name) const {
|
||||||
|
|
||||||
void AvatarData::setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation) {
|
void AvatarData::setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "setJointData", Q_ARG(const QString&, name),
|
QMetaObject::invokeMethod(this, "setJointData", Q_ARG(const QString&, name), Q_ARG(const glm::quat&, rotation),
|
||||||
Q_ARG(const glm::quat&, rotation));
|
Q_ARG(const glm::vec3&, translation));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setJointData(getJointIndex(name), rotation, translation);
|
setJointData(getJointIndex(name), rotation, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarData::setJointRotation(const QString& name, const glm::quat& rotation) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "setJointRotation", Q_ARG(const QString&, name), Q_ARG(const glm::quat&, rotation));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setJointRotation(getJointIndex(name), rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarData::setJointTranslation(const QString& name, const glm::vec3& translation) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "setJointTranslation", Q_ARG(const QString&, name),
|
||||||
|
Q_ARG(const glm::vec3&, translation));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setJointTranslation(getJointIndex(name), translation);
|
||||||
|
}
|
||||||
|
|
||||||
void AvatarData::setJointRotation(int index, const glm::quat& rotation) {
|
void AvatarData::setJointRotation(int index, const glm::quat& rotation) {
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -251,6 +251,8 @@ public:
|
||||||
Q_INVOKABLE virtual glm::vec3 getJointTranslation(int index) const;
|
Q_INVOKABLE virtual glm::vec3 getJointTranslation(int index) const;
|
||||||
|
|
||||||
Q_INVOKABLE void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation);
|
Q_INVOKABLE void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation);
|
||||||
|
Q_INVOKABLE void setJointRotation(const QString& name, const glm::quat& rotation);
|
||||||
|
Q_INVOKABLE void setJointTranslation(const QString& name, const glm::vec3& translation);
|
||||||
Q_INVOKABLE void clearJointData(const QString& name);
|
Q_INVOKABLE void clearJointData(const QString& name);
|
||||||
Q_INVOKABLE bool isJointDataValid(const QString& name) const;
|
Q_INVOKABLE bool isJointDataValid(const QString& name) const;
|
||||||
Q_INVOKABLE glm::quat getJointRotation(const QString& name) const;
|
Q_INVOKABLE glm::quat getJointRotation(const QString& name) const;
|
||||||
|
|
|
@ -93,6 +93,177 @@ QVector<QString> UserInputMapper::getDeviceNames() {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserInputMapper::Input UserInputMapper::findDeviceInput(const QString& inputName) const {
|
UserInputMapper::Input UserInputMapper::findDeviceInput(const QString& inputName) const {
|
||||||
|
/*=======
|
||||||
|
|
||||||
|
// Default contruct allocate the poutput size with the current hardcoded action channels
|
||||||
|
UserInputMapper::UserInputMapper() {
|
||||||
|
registerStandardDevice();
|
||||||
|
assignDefaulActionScales();
|
||||||
|
createActionNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInputMapper::~UserInputMapper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int UserInputMapper::recordDeviceOfType(const QString& deviceName) {
|
||||||
|
if (!_deviceCounts.contains(deviceName)) {
|
||||||
|
_deviceCounts[deviceName] = 0;
|
||||||
|
}
|
||||||
|
_deviceCounts[deviceName] += 1;
|
||||||
|
|
||||||
|
return _deviceCounts[deviceName];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer& proxy) {
|
||||||
|
int numberOfType = recordDeviceOfType(proxy->_name);
|
||||||
|
|
||||||
|
if (numberOfType > 1) {
|
||||||
|
proxy->_name += QString::number(numberOfType);
|
||||||
|
}
|
||||||
|
|
||||||
|
_registeredDevices[deviceID] = proxy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInputMapper::DeviceProxy::Pointer UserInputMapper::getDeviceProxy(const Input& input) {
|
||||||
|
auto device = _registeredDevices.find(input.getDevice());
|
||||||
|
if (device != _registeredDevices.end()) {
|
||||||
|
return (device->second);
|
||||||
|
} else {
|
||||||
|
return DeviceProxy::Pointer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UserInputMapper::getDeviceName(uint16 deviceID) {
|
||||||
|
if (_registeredDevices.find(deviceID) != _registeredDevices.end()) {
|
||||||
|
return _registeredDevices[deviceID]->_name;
|
||||||
|
}
|
||||||
|
return QString("unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UserInputMapper::resetAllDeviceBindings() {
|
||||||
|
for (auto device : _registeredDevices) {
|
||||||
|
device.second->resetDeviceBindings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserInputMapper::resetDevice(uint16 deviceID) {
|
||||||
|
auto device = _registeredDevices.find(deviceID);
|
||||||
|
if (device != _registeredDevices.end()) {
|
||||||
|
device->second->resetDeviceBindings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int UserInputMapper::findDevice(QString name) {
|
||||||
|
for (auto device : _registeredDevices) {
|
||||||
|
if (device.second->_name.split(" (")[0] == name) {
|
||||||
|
return device.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> UserInputMapper::getDeviceNames() {
|
||||||
|
QVector<QString> result;
|
||||||
|
for (auto device : _registeredDevices) {
|
||||||
|
QString deviceName = device.second->_name.split(" (")[0];
|
||||||
|
result << deviceName;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) {
|
||||||
|
return addInputChannel(action, input, Input(), scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserInputMapper::addInputChannel(Action action, const Input& input, const Input& modifier, float scale) {
|
||||||
|
// Check that the device is registered
|
||||||
|
if (!getDeviceProxy(input)) {
|
||||||
|
qDebug() << "UserInputMapper::addInputChannel: The input comes from a device #" << input.getDevice() << "is unknown. no inputChannel mapped.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto inputChannel = InputChannel(input, modifier, action, scale);
|
||||||
|
|
||||||
|
// Insert or replace the input to modifiers
|
||||||
|
if (inputChannel.hasModifier()) {
|
||||||
|
auto& modifiers = _inputToModifiersMap[input.getID()];
|
||||||
|
modifiers.push_back(inputChannel._modifier);
|
||||||
|
std::sort(modifiers.begin(), modifiers.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now update the action To Inputs side of things
|
||||||
|
_actionToInputsMap.insert(ActionToInputsMap::value_type(action, inputChannel));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UserInputMapper::addInputChannels(const InputChannels& channels) {
|
||||||
|
int nbAdded = 0;
|
||||||
|
for (auto& channel : channels) {
|
||||||
|
nbAdded += addInputChannel(channel._action, channel._input, channel._modifier, channel._scale);
|
||||||
|
}
|
||||||
|
return nbAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserInputMapper::removeInputChannel(InputChannel inputChannel) {
|
||||||
|
// Remove from Input to Modifiers map
|
||||||
|
if (inputChannel.hasModifier()) {
|
||||||
|
_inputToModifiersMap.erase(inputChannel._input.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from Action to Inputs map
|
||||||
|
std::pair<ActionToInputsMap::iterator, ActionToInputsMap::iterator> ret;
|
||||||
|
ret = _actionToInputsMap.equal_range(inputChannel._action);
|
||||||
|
for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) {
|
||||||
|
if (it->second == inputChannel) {
|
||||||
|
_actionToInputsMap.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserInputMapper::removeAllInputChannels() {
|
||||||
|
_inputToModifiersMap.clear();
|
||||||
|
_actionToInputsMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserInputMapper::removeAllInputChannelsForDevice(uint16 device) {
|
||||||
|
QVector<InputChannel> channels = getAllInputsForDevice(device);
|
||||||
|
for (auto& channel : channels) {
|
||||||
|
removeInputChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserInputMapper::removeDevice(int device) {
|
||||||
|
removeAllInputChannelsForDevice((uint16) device);
|
||||||
|
_registeredDevices.erase(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int UserInputMapper::getInputChannels(InputChannels& channels) const {
|
||||||
|
for (auto& channel : _actionToInputsMap) {
|
||||||
|
channels.push_back(channel.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _actionToInputsMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<UserInputMapper::InputChannel> UserInputMapper::getAllInputsForDevice(uint16 device) {
|
||||||
|
InputChannels allChannels;
|
||||||
|
getInputChannels(allChannels);
|
||||||
|
|
||||||
|
QVector<InputChannel> channels;
|
||||||
|
for (InputChannel inputChannel : allChannels) {
|
||||||
|
if (inputChannel._input._device == device) {
|
||||||
|
channels.push_back(inputChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>>>>>>> 80cffdb764d3faa5516c8b0eb0a49d84cc395416*/
|
||||||
|
|
||||||
// Split the full input name as such: deviceName.inputName
|
// Split the full input name as such: deviceName.inputName
|
||||||
auto names = inputName.split('.');
|
auto names = inputName.split('.');
|
||||||
|
|
|
@ -136,6 +136,7 @@ public:
|
||||||
};
|
};
|
||||||
// GetFreeDeviceID should be called before registering a device to use an ID not used by a different device.
|
// GetFreeDeviceID should be called before registering a device to use an ID not used by a different device.
|
||||||
uint16 getFreeDeviceID() { return _nextFreeDeviceID++; }
|
uint16 getFreeDeviceID() { return _nextFreeDeviceID++; }
|
||||||
|
|
||||||
bool registerDevice(uint16 deviceID, const DeviceProxy::Pointer& device);
|
bool registerDevice(uint16 deviceID, const DeviceProxy::Pointer& device);
|
||||||
bool registerStandardDevice(const DeviceProxy::Pointer& device) { _standardDevice = device; return true; }
|
bool registerStandardDevice(const DeviceProxy::Pointer& device) { _standardDevice = device; return true; }
|
||||||
DeviceProxy::Pointer getDeviceProxy(const Input& input);
|
DeviceProxy::Pointer getDeviceProxy(const Input& input);
|
||||||
|
@ -299,6 +300,9 @@ protected:
|
||||||
std::vector<PoseValue> _poseStates = std::vector<PoseValue>(NUM_ACTIONS);
|
std::vector<PoseValue> _poseStates = std::vector<PoseValue>(NUM_ACTIONS);
|
||||||
|
|
||||||
glm::mat4 _sensorToWorldMat;
|
glm::mat4 _sensorToWorldMat;
|
||||||
|
|
||||||
|
int recordDeviceOfType(const QString& deviceName);
|
||||||
|
QHash<const QString&, int> _deviceCounts;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(UserInputMapper::InputPair)
|
Q_DECLARE_METATYPE(UserInputMapper::InputPair)
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
|
#include <plugins/PluginContainer.h>
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
|
||||||
// A base class for FBO wrappers that need to use the Oculus C
|
// A base class for FBO wrappers that need to use the Oculus C
|
||||||
|
@ -135,6 +137,19 @@ const QString & OculusDisplayPlugin::getName() const {
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QString MONO_PREVIEW = "Mono Preview";
|
||||||
|
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
||||||
|
|
||||||
|
void OculusDisplayPlugin::activate() {
|
||||||
|
|
||||||
|
CONTAINER->addMenuItem(MENU_PATH(), MONO_PREVIEW,
|
||||||
|
[this](bool clicked) {
|
||||||
|
_monoPreview = clicked;
|
||||||
|
}, true, true);
|
||||||
|
CONTAINER->removeMenu(FRAMERATE);
|
||||||
|
OculusBaseDisplayPlugin::activate();
|
||||||
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::customizeContext() {
|
void OculusDisplayPlugin::customizeContext() {
|
||||||
WindowOpenGLDisplayPlugin::customizeContext();
|
WindowOpenGLDisplayPlugin::customizeContext();
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
@ -149,7 +164,7 @@ void OculusDisplayPlugin::customizeContext() {
|
||||||
#endif
|
#endif
|
||||||
enableVsync(false);
|
enableVsync(false);
|
||||||
// Only enable mirroring if we know vsync is disabled
|
// Only enable mirroring if we know vsync is disabled
|
||||||
_enableMirror = !isVsyncEnabled();
|
_enablePreview = !isVsyncEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::deactivate() {
|
void OculusDisplayPlugin::deactivate() {
|
||||||
|
@ -169,10 +184,15 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
// controlling vsync
|
// controlling vsync
|
||||||
wglSwapIntervalEXT(0);
|
wglSwapIntervalEXT(0);
|
||||||
|
|
||||||
// screen mirroring
|
// screen preview mirroring
|
||||||
if (_enableMirror) {
|
if (_enablePreview) {
|
||||||
auto windowSize = toGlm(_window->size());
|
auto windowSize = toGlm(_window->size());
|
||||||
Context::Viewport(windowSize.x, windowSize.y);
|
if (_monoPreview) {
|
||||||
|
Context::Viewport(windowSize.x * 2, windowSize.y);
|
||||||
|
Context::Scissor(0, windowSize.y, windowSize.x, windowSize.y);
|
||||||
|
} else {
|
||||||
|
Context::Viewport(windowSize.x, windowSize.y);
|
||||||
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, finalTexture);
|
glBindTexture(GL_TEXTURE_2D, finalTexture);
|
||||||
GLenum err = glGetError();
|
GLenum err = glGetError();
|
||||||
Q_ASSERT(0 == err);
|
Q_ASSERT(0 == err);
|
||||||
|
@ -216,7 +236,7 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
otherwise the swapbuffer delay will interefere with the framerate of the headset
|
otherwise the swapbuffer delay will interefere with the framerate of the headset
|
||||||
*/
|
*/
|
||||||
void OculusDisplayPlugin::finishFrame() {
|
void OculusDisplayPlugin::finishFrame() {
|
||||||
if (_enableMirror) {
|
if (_enablePreview) {
|
||||||
swapBuffers();
|
swapBuffers();
|
||||||
}
|
}
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
|
|
|
@ -14,6 +14,7 @@ using SwapFboPtr = QSharedPointer<SwapFramebufferWrapper>;
|
||||||
|
|
||||||
class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
|
virtual void activate() override;
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
virtual const QString & getName() const override;
|
virtual const QString & getName() const override;
|
||||||
|
|
||||||
|
@ -25,7 +26,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
bool _enableMirror{ false };
|
bool _enablePreview { false };
|
||||||
|
bool _monoPreview { true };
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
SwapFboPtr _sceneFbo;
|
SwapFboPtr _sceneFbo;
|
||||||
|
|
|
@ -61,6 +61,8 @@ glm::mat4 StereoDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProje
|
||||||
return eyeProjection;
|
return eyeProjection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
||||||
|
|
||||||
std::vector<QAction*> _screenActions;
|
std::vector<QAction*> _screenActions;
|
||||||
void StereoDisplayPlugin::activate() {
|
void StereoDisplayPlugin::activate() {
|
||||||
auto screens = qApp->screens();
|
auto screens = qApp->screens();
|
||||||
|
@ -76,6 +78,9 @@ void StereoDisplayPlugin::activate() {
|
||||||
[this](bool clicked) { updateScreen(); }, true, checked, "Screens");
|
[this](bool clicked) { updateScreen(); }, true, checked, "Screens");
|
||||||
_screenActions[i] = action;
|
_screenActions[i] = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONTAINER->removeMenu(FRAMERATE);
|
||||||
|
|
||||||
CONTAINER->setFullscreen(qApp->primaryScreen());
|
CONTAINER->setFullscreen(qApp->primaryScreen());
|
||||||
WindowOpenGLDisplayPlugin::activate();
|
WindowOpenGLDisplayPlugin::activate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ void SixenseManager::activate() {
|
||||||
#endif
|
#endif
|
||||||
loadSettings();
|
loadSettings();
|
||||||
sixenseInit();
|
sixenseInit();
|
||||||
|
_activated = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +139,7 @@ void SixenseManager::deactivate() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sixenseExit();
|
sixenseExit();
|
||||||
|
_activated = false;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
delete _sixenseLibrary;
|
delete _sixenseLibrary;
|
||||||
|
@ -157,6 +159,12 @@ void SixenseManager::setSixenseFilter(bool filter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::update(float deltaTime, bool jointsCaptured) {
|
void SixenseManager::update(float deltaTime, bool jointsCaptured) {
|
||||||
|
// FIXME - Some of the code in update() will crash if you haven't actually activated the
|
||||||
|
// plugin. But we want register with the UserInputMapper if we don't call this.
|
||||||
|
// We need to clean this up.
|
||||||
|
//if (!_activated) {
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
_buttonPressedMap.clear();
|
_buttonPressedMap.clear();
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,9 @@ private:
|
||||||
|
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
static const QString HYDRA_ID_STRING;
|
static const QString HYDRA_ID_STRING;
|
||||||
|
|
||||||
|
bool _activated = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_SixenseManager_h
|
#endif // hifi_SixenseManager_h
|
||||||
|
|
|
@ -65,43 +65,65 @@ void AssetClient::init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
AssetRequest* AssetClient::createRequest(const QString& hash, const QString& extension) {
|
AssetRequest* AssetClient::createRequest(const QString& hash, const QString& extension) {
|
||||||
if (hash.length() != SHA256_HASH_HEX_LENGTH) {
|
if (hash.length() != SHA256_HASH_HEX_LENGTH) {
|
||||||
qCWarning(asset_client) << "Invalid hash size";
|
qCWarning(asset_client) << "Invalid hash size";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
if (haveAssetServer()) {
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
auto request = new AssetRequest(hash, extension);
|
||||||
|
|
||||||
if (!assetServer) {
|
// Move to the AssetClient thread in case we are not currently on that thread (which will usually be the case)
|
||||||
qCWarning(asset_client).nospace() << "Could not request " << hash << "." << extension
|
request->moveToThread(thread());
|
||||||
<< " since you are not currently connected to an asset-server.";
|
request->setParent(this);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto request = new AssetRequest(hash, extension);
|
|
||||||
|
|
||||||
// Move to the AssetClient thread in case we are not currently on that thread (which will usually be the case)
|
|
||||||
request->moveToThread(thread());
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AssetUpload* AssetClient::createUpload(const QString& filename) {
|
AssetUpload* AssetClient::createUpload(const QString& filename) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
|
||||||
|
|
||||||
if (!assetServer) {
|
if (haveAssetServer()) {
|
||||||
qCWarning(asset_client) << "Could not upload" << filename << "since you are not currently connected to an asset-server.";
|
auto upload = new AssetUpload(filename);
|
||||||
|
|
||||||
|
upload->moveToThread(thread());
|
||||||
|
upload->setParent(this);
|
||||||
|
|
||||||
|
return upload;
|
||||||
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto upload = new AssetUpload(this, filename);
|
|
||||||
|
|
||||||
upload->moveToThread(thread());
|
AssetUpload* AssetClient::createUpload(const QByteArray& data, const QString& extension) {
|
||||||
|
if (haveAssetServer()) {
|
||||||
return upload;
|
auto upload = new AssetUpload(data, extension);
|
||||||
|
|
||||||
|
upload->moveToThread(thread());
|
||||||
|
upload->setParent(this);
|
||||||
|
|
||||||
|
return upload;
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetClient::getAsset(const QString& hash, const QString& extension, DataOffset start, DataOffset end,
|
bool AssetClient::getAsset(const QString& hash, const QString& extension, DataOffset start, DataOffset end,
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE AssetRequest* createRequest(const QString& hash, const QString& extension);
|
Q_INVOKABLE AssetRequest* createRequest(const QString& hash, const QString& extension);
|
||||||
Q_INVOKABLE AssetUpload* createUpload(const QString& filename);
|
Q_INVOKABLE AssetUpload* createUpload(const QString& filename);
|
||||||
|
Q_INVOKABLE AssetUpload* createUpload(const QByteArray& data, const QString& extension);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleAssetGetInfoReply(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
void handleAssetGetInfoReply(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
||||||
|
|
|
@ -127,8 +127,3 @@ void AssetRequest::start() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl AssetRequest::getUrl() const {
|
|
||||||
return ::getUrl(_hash, _extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
const QByteArray& getData() const { return _data; }
|
const QByteArray& getData() const { return _data; }
|
||||||
const State& getState() const { return _state; }
|
const State& getState() const { return _state; }
|
||||||
const Error& getError() const { return _error; }
|
const Error& getError() const { return _error; }
|
||||||
QUrl getUrl() const;
|
QUrl getUrl() const { return ::getATPUrl(_hash, _extension); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished(AssetRequest* thisRequest);
|
void finished(AssetRequest* thisRequest);
|
||||||
|
|
|
@ -17,65 +17,94 @@
|
||||||
#include "AssetClient.h"
|
#include "AssetClient.h"
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
|
|
||||||
AssetUpload::AssetUpload(QObject* object, const QString& filename) :
|
const QString AssetUpload::PERMISSION_DENIED_ERROR = "You do not have permission to upload content to this asset-server.";
|
||||||
|
|
||||||
|
AssetUpload::AssetUpload(const QByteArray& data, const QString& extension) :
|
||||||
|
_data(data),
|
||||||
|
_extension(extension)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetUpload::AssetUpload(const QString& filename) :
|
||||||
_filename(filename)
|
_filename(filename)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString AssetUpload::getErrorString() const {
|
||||||
|
// figure out the right error message for error
|
||||||
|
switch (_error) {
|
||||||
|
case AssetUpload::PermissionDenied:
|
||||||
|
return PERMISSION_DENIED_ERROR;
|
||||||
|
case AssetUpload::TooLarge:
|
||||||
|
return "The uploaded content was too large and could not be stored in the asset-server.";
|
||||||
|
case AssetUpload::FileOpenError:
|
||||||
|
return "The file could not be opened. Please check your permissions and try again.";
|
||||||
|
case AssetUpload::NetworkError:
|
||||||
|
return "The file could not be opened. Please check your network connectivity.";
|
||||||
|
default:
|
||||||
|
// not handled, do not show a message box
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AssetUpload::start() {
|
void AssetUpload::start() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "start");
|
QMetaObject::invokeMethod(this, "start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to open the file at the given filename
|
if (_data.isEmpty() && !_filename.isEmpty()) {
|
||||||
QFile file { _filename };
|
// try to open the file at the given filename
|
||||||
|
QFile file { _filename };
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
|
||||||
|
|
||||||
// file opened, read the data and grab the extension
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
_extension = QFileInfo(_filename).suffix();
|
|
||||||
|
|
||||||
_data = file.readAll();
|
|
||||||
|
|
||||||
// ask the AssetClient to upload the asset and emit the proper signals from the passed callback
|
|
||||||
auto assetClient = DependencyManager::get<AssetClient>();
|
|
||||||
|
|
||||||
qCDebug(asset_client) << "Attempting to upload" << _filename << "to asset-server.";
|
|
||||||
|
|
||||||
assetClient->uploadAsset(_data, _extension, [this](bool responseReceived, AssetServerError error,
|
|
||||||
const QString& hash){
|
|
||||||
if (!responseReceived) {
|
|
||||||
_error = NetworkError;
|
|
||||||
} else {
|
|
||||||
switch (error) {
|
|
||||||
case AssetServerError::NoError:
|
|
||||||
_error = NoError;
|
|
||||||
break;
|
|
||||||
case AssetServerError::AssetTooLarge:
|
|
||||||
_error = TooLarge;
|
|
||||||
break;
|
|
||||||
case AssetServerError::PermissionDenied:
|
|
||||||
_error = PermissionDenied;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_error = FileOpenError;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_error == NoError && hash == hashData(_data).toHex()) {
|
// file opened, read the data and grab the extension
|
||||||
saveToCache(getUrl(hash, _extension), _data);
|
_extension = QFileInfo(_filename).suffix();
|
||||||
}
|
|
||||||
|
|
||||||
emit finished(this, hash);
|
_data = file.readAll();
|
||||||
});
|
} else {
|
||||||
} else {
|
// we couldn't open the file - set the error result
|
||||||
// we couldn't open the file - set the error result
|
_error = FileOpenError;
|
||||||
_error = FileOpenError;
|
|
||||||
|
// emit that we are done
|
||||||
// emit that we are done
|
emit finished(this, QString());
|
||||||
emit finished(this, QString());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ask the AssetClient to upload the asset and emit the proper signals from the passed callback
|
||||||
|
auto assetClient = DependencyManager::get<AssetClient>();
|
||||||
|
|
||||||
|
if (!_filename.isEmpty()) {
|
||||||
|
qCDebug(asset_client) << "Attempting to upload" << _filename << "to asset-server.";
|
||||||
|
}
|
||||||
|
|
||||||
|
assetClient->uploadAsset(_data, _extension, [this](bool responseReceived, AssetServerError error, const QString& hash){
|
||||||
|
if (!responseReceived) {
|
||||||
|
_error = NetworkError;
|
||||||
|
} else {
|
||||||
|
switch (error) {
|
||||||
|
case AssetServerError::NoError:
|
||||||
|
_error = NoError;
|
||||||
|
break;
|
||||||
|
case AssetServerError::AssetTooLarge:
|
||||||
|
_error = TooLarge;
|
||||||
|
break;
|
||||||
|
case AssetServerError::PermissionDenied:
|
||||||
|
_error = PermissionDenied;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_error = FileOpenError;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_error == NoError && hash == hashData(_data).toHex()) {
|
||||||
|
saveToCache(getATPUrl(hash, _extension), _data);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit finished(this, hash);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,17 @@ public:
|
||||||
FileOpenError
|
FileOpenError
|
||||||
};
|
};
|
||||||
|
|
||||||
AssetUpload(QObject* parent, const QString& filename);
|
static const QString PERMISSION_DENIED_ERROR;
|
||||||
|
|
||||||
|
AssetUpload(const QString& filename);
|
||||||
|
AssetUpload(const QByteArray& data, const QString& extension);
|
||||||
|
|
||||||
Q_INVOKABLE void start();
|
Q_INVOKABLE void start();
|
||||||
|
|
||||||
const QString& getFilename() const { return _filename; }
|
const QString& getFilename() const { return _filename; }
|
||||||
const QString& getExtension() const { return _extension; }
|
const QString& getExtension() const { return _extension; }
|
||||||
const Error& getError() const { return _error; }
|
const Error& getError() const { return _error; }
|
||||||
|
QString getErrorString() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished(AssetUpload* upload, const QString& hash);
|
void finished(AssetUpload* upload, const QString& hash);
|
||||||
|
@ -49,8 +53,8 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _filename;
|
QString _filename;
|
||||||
QString _extension;
|
|
||||||
QByteArray _data;
|
QByteArray _data;
|
||||||
|
QString _extension;
|
||||||
Error _error;
|
Error _error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "ResourceManager.h"
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
QUrl getUrl(const QString& hash, const QString& extension) {
|
QUrl getATPUrl(const QString& hash, const QString& extension) {
|
||||||
if (!extension.isEmpty()) {
|
if (!extension.isEmpty()) {
|
||||||
return QUrl(QString("%1:%2.%3").arg(URL_SCHEME_ATP, hash, extension));
|
return QUrl(QString("%1:%2.%3").arg(URL_SCHEME_ATP, hash, extension));
|
||||||
} else {
|
} else {
|
||||||
|
@ -66,4 +66,4 @@ bool saveToCache(const QUrl& url, const QByteArray& file) {
|
||||||
qCWarning(asset_client) << "No disk cache to save assets to.";
|
qCWarning(asset_client) << "No disk cache to save assets to.";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ enum AssetServerError : uint8_t {
|
||||||
PermissionDenied
|
PermissionDenied
|
||||||
};
|
};
|
||||||
|
|
||||||
QUrl getUrl(const QString& hash, const QString& extension = QString());
|
QUrl getATPUrl(const QString& hash, const QString& extension = QString());
|
||||||
|
|
||||||
QByteArray hashData(const QByteArray& data);
|
QByteArray hashData(const QByteArray& data);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ bool ReceivedPacketProcessor::process() {
|
||||||
float incomingPacketsPerSecondInWindow = (float)_lastWindowIncomingPackets / secondsSinceLastWindow;
|
float incomingPacketsPerSecondInWindow = (float)_lastWindowIncomingPackets / secondsSinceLastWindow;
|
||||||
_incomingPPS.updateAverage(incomingPacketsPerSecondInWindow);
|
_incomingPPS.updateAverage(incomingPacketsPerSecondInWindow);
|
||||||
|
|
||||||
float processedPacketsPerSecondInWindow = (float)_lastWindowIncomingPackets / secondsSinceLastWindow;
|
float processedPacketsPerSecondInWindow = (float)_lastWindowProcessedPackets / secondsSinceLastWindow;
|
||||||
_processedPPS.updateAverage(processedPacketsPerSecondInWindow);
|
_processedPPS.updateAverage(processedPacketsPerSecondInWindow);
|
||||||
|
|
||||||
_lastWindowAt = now;
|
_lastWindowAt = now;
|
||||||
|
|
Loading…
Reference in a new issue