mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:37:51 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into remap-keybaord
This commit is contained in:
commit
b8796db1e5
19 changed files with 389 additions and 129 deletions
|
@ -46,15 +46,68 @@ static const uint8_t CPU_AFFINITY_COUNT_LOW = 1;
|
||||||
static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
|
||||||
|
|
||||||
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
||||||
static QStringList BAKEABLE_TEXTURE_EXTENSIONS;
|
static QStringList BAKEABLE_TEXTURE_EXTENSIONS;
|
||||||
static const QStringList BAKEABLE_SCRIPT_EXTENSIONS = {};
|
static const QStringList BAKEABLE_SCRIPT_EXTENSIONS = { };
|
||||||
|
|
||||||
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
|
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
|
||||||
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
||||||
static const QString BAKED_SCRIPT_SIMPLE_NAME = "asset.js";
|
static const QString BAKED_SCRIPT_SIMPLE_NAME = "asset.js";
|
||||||
|
|
||||||
|
static const ModelBakeVersion CURRENT_MODEL_BAKE_VERSION = (ModelBakeVersion)((BakeVersion)ModelBakeVersion::COUNT - 1);
|
||||||
|
static const TextureBakeVersion CURRENT_TEXTURE_BAKE_VERSION = (TextureBakeVersion)((BakeVersion)TextureBakeVersion::COUNT - 1);
|
||||||
|
static const ScriptBakeVersion CURRENT_SCRIPT_BAKE_VERSION = (ScriptBakeVersion)((BakeVersion)ScriptBakeVersion::COUNT - 1);
|
||||||
|
|
||||||
|
BakedAssetType assetTypeForExtension(const QString& extension) {
|
||||||
|
auto extensionLower = extension.toLower();
|
||||||
|
if (BAKEABLE_MODEL_EXTENSIONS.contains(extensionLower)) {
|
||||||
|
return Model;
|
||||||
|
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extensionLower.toLocal8Bit())) {
|
||||||
|
return Texture;
|
||||||
|
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extensionLower)) {
|
||||||
|
return Script;
|
||||||
|
}
|
||||||
|
return Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
BakedAssetType assetTypeForFilename(const QString& filename) {
|
||||||
|
auto dotIndex = filename.lastIndexOf(".");
|
||||||
|
if (dotIndex == -1) {
|
||||||
|
return BakedAssetType::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto extension = filename.mid(dotIndex + 1);
|
||||||
|
return assetTypeForExtension(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString bakedFilenameForAssetType(BakedAssetType type) {
|
||||||
|
switch (type) {
|
||||||
|
case Model:
|
||||||
|
return BAKED_MODEL_SIMPLE_NAME;
|
||||||
|
case Texture:
|
||||||
|
return BAKED_TEXTURE_SIMPLE_NAME;
|
||||||
|
case Script:
|
||||||
|
return BAKED_SCRIPT_SIMPLE_NAME;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BakeVersion currentBakeVersionForAssetType(BakedAssetType type) {
|
||||||
|
switch (type) {
|
||||||
|
case Model:
|
||||||
|
return (BakeVersion)CURRENT_MODEL_BAKE_VERSION;
|
||||||
|
case Texture:
|
||||||
|
return (BakeVersion)CURRENT_TEXTURE_BAKE_VERSION;
|
||||||
|
case Script:
|
||||||
|
return (BakeVersion)CURRENT_SCRIPT_BAKE_VERSION;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||||
|
|
||||||
void AssetServer::bakeAsset(const AssetUtils::AssetHash& assetHash, const AssetUtils::AssetPath& assetPath, const QString& filePath) {
|
void AssetServer::bakeAsset(const AssetUtils::AssetHash& assetHash, const AssetUtils::AssetPath& assetPath, const QString& filePath) {
|
||||||
qDebug() << "Starting bake for: " << assetPath << assetHash;
|
qDebug() << "Starting bake for: " << assetPath << assetHash;
|
||||||
auto it = _pendingBakes.find(assetHash);
|
auto it = _pendingBakes.find(assetHash);
|
||||||
|
@ -167,36 +220,38 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dotIndex = path.lastIndexOf(".");
|
BakedAssetType type = assetTypeForFilename(path);
|
||||||
if (dotIndex == -1) {
|
|
||||||
|
if (type == Undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto extension = path.mid(dotIndex + 1);
|
QString bakedFilename = bakedFilenameForAssetType(type);
|
||||||
|
auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + assetHash + "/" + bakedFilename;
|
||||||
|
auto mappingIt = _fileMappings.find(bakedPath);
|
||||||
|
bool bakedMappingExists = mappingIt != _fileMappings.end();
|
||||||
|
|
||||||
QString bakedFilename;
|
// If the path is mapped to the original file's hash, baking has been disabled for this
|
||||||
|
// asset
|
||||||
|
if (bakedMappingExists && mappingIt->second == assetHash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool loaded;
|
bool loaded;
|
||||||
AssetMeta meta;
|
AssetMeta meta;
|
||||||
std::tie(loaded, meta) = readMetaFile(assetHash);
|
std::tie(loaded, meta) = readMetaFile(assetHash);
|
||||||
|
|
||||||
// TODO: Allow failed bakes that happened on old versions to be re-baked
|
if (type == Texture && !loaded) {
|
||||||
if (loaded && meta.failedLastBake) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(extension)) {
|
auto currentVersion = currentBakeVersionForAssetType(type);
|
||||||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
|
||||||
} else if (loaded && BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit())) {
|
if (loaded && (meta.failedLastBake && meta.bakeVersion >= currentVersion)) {
|
||||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
|
||||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
|
||||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + assetHash + "/" + bakedFilename;
|
return !bakedMappingExists || (meta.bakeVersion < currentVersion);
|
||||||
return _fileMappings.find(bakedPath) == _fileMappings.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool interfaceRunning() {
|
bool interfaceRunning() {
|
||||||
|
@ -598,15 +653,9 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi
|
||||||
|
|
||||||
// first, figure out from the mapping extension what type of file this is
|
// first, figure out from the mapping extension what type of file this is
|
||||||
auto assetPathExtension = assetPath.mid(assetPath.lastIndexOf('.') + 1).toLower();
|
auto assetPathExtension = assetPath.mid(assetPath.lastIndexOf('.') + 1).toLower();
|
||||||
QString bakedRootFile;
|
|
||||||
|
|
||||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(assetPathExtension)) {
|
auto type = assetTypeForFilename(assetPath);
|
||||||
bakedRootFile = BAKED_MODEL_SIMPLE_NAME;
|
QString bakedRootFile = bakedFilenameForAssetType(type);
|
||||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(assetPathExtension.toLocal8Bit())) {
|
|
||||||
bakedRootFile = BAKED_TEXTURE_SIMPLE_NAME;
|
|
||||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(assetPathExtension)) {
|
|
||||||
bakedRootFile = BAKED_SCRIPT_SIMPLE_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto originalAssetHash = it->second;
|
auto originalAssetHash = it->second;
|
||||||
QString redirectedAssetHash;
|
QString redirectedAssetHash;
|
||||||
|
@ -653,9 +702,19 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi
|
||||||
auto query = QUrlQuery(url.query());
|
auto query = QUrlQuery(url.query());
|
||||||
bool isSkybox = query.hasQueryItem("skybox");
|
bool isSkybox = query.hasQueryItem("skybox");
|
||||||
if (isSkybox) {
|
if (isSkybox) {
|
||||||
writeMetaFile(originalAssetHash);
|
bool loaded;
|
||||||
if (!bakingDisabled) {
|
AssetMeta meta;
|
||||||
maybeBake(assetPath, originalAssetHash);
|
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
|
||||||
|
|
||||||
|
if (!loaded) {
|
||||||
|
AssetMeta needsBakingMeta;
|
||||||
|
needsBakingMeta.bakeVersion = NEEDS_BAKING_BAKE_VERSION;
|
||||||
|
|
||||||
|
writeMetaFile(originalAssetHash, needsBakingMeta);
|
||||||
|
if (!bakingDisabled) {
|
||||||
|
maybeBake(assetPath, originalAssetHash);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1275,15 +1334,19 @@ QString getBakeMapping(const AssetUtils::AssetHash& hash, const QString& relativ
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, QString errors) {
|
void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, QString errors) {
|
||||||
qDebug() << "Failed: " << originalAssetHash << assetPath << errors;
|
qDebug() << "Failed to bake: " << originalAssetHash << assetPath << "(" << errors << ")";
|
||||||
|
|
||||||
bool loaded;
|
bool loaded;
|
||||||
AssetMeta meta;
|
AssetMeta meta;
|
||||||
|
|
||||||
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
|
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
|
||||||
|
|
||||||
|
auto type = assetTypeForFilename(assetPath);
|
||||||
|
auto currentTypeVersion = currentBakeVersionForAssetType(type);
|
||||||
|
|
||||||
meta.failedLastBake = true;
|
meta.failedLastBake = true;
|
||||||
meta.lastBakeErrors = errors;
|
meta.lastBakeErrors = errors;
|
||||||
|
meta.bakeVersion = currentTypeVersion;
|
||||||
|
|
||||||
writeMetaFile(originalAssetHash, meta);
|
writeMetaFile(originalAssetHash, meta);
|
||||||
|
|
||||||
|
@ -1373,17 +1436,20 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina
|
||||||
qWarning() << "Failed to remove temporary directory:" << bakedTempOutputDir;
|
qWarning() << "Failed to remove temporary directory:" << bakedTempOutputDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errorCompletingBake) {
|
auto type = assetTypeForFilename(originalAssetPath);
|
||||||
// create the meta file to store which version of the baking process we just completed
|
auto currentTypeVersion = currentBakeVersionForAssetType(type);
|
||||||
writeMetaFile(originalAssetHash);
|
|
||||||
} else {
|
AssetMeta meta;
|
||||||
|
meta.bakeVersion = currentTypeVersion;
|
||||||
|
meta.failedLastBake = errorCompletingBake;
|
||||||
|
|
||||||
|
if (errorCompletingBake) {
|
||||||
qWarning() << "Could not complete bake for" << originalAssetHash;
|
qWarning() << "Could not complete bake for" << originalAssetHash;
|
||||||
AssetMeta meta;
|
|
||||||
meta.failedLastBake = true;
|
|
||||||
meta.lastBakeErrors = errorReason;
|
meta.lastBakeErrors = errorReason;
|
||||||
writeMetaFile(originalAssetHash, meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeMetaFile(originalAssetHash, meta);
|
||||||
|
|
||||||
_pendingBakes.remove(originalAssetHash);
|
_pendingBakes.remove(originalAssetHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,7 +1513,7 @@ bool AssetServer::writeMetaFile(AssetUtils::AssetHash originalAssetHash, const A
|
||||||
// construct the JSON that will be in the meta file
|
// construct the JSON that will be in the meta file
|
||||||
QJsonObject metaFileObject;
|
QJsonObject metaFileObject;
|
||||||
|
|
||||||
metaFileObject[BAKE_VERSION_KEY] = meta.bakeVersion;
|
metaFileObject[BAKE_VERSION_KEY] = (int)meta.bakeVersion;
|
||||||
metaFileObject[FAILED_LAST_BAKE_KEY] = meta.failedLastBake;
|
metaFileObject[FAILED_LAST_BAKE_KEY] = meta.failedLastBake;
|
||||||
metaFileObject[LAST_BAKE_ERRORS_KEY] = meta.lastBakeErrors;
|
metaFileObject[LAST_BAKE_ERRORS_KEY] = meta.lastBakeErrors;
|
||||||
|
|
||||||
|
@ -1479,27 +1545,13 @@ bool AssetServer::setBakingEnabled(const AssetUtils::AssetPathList& paths, bool
|
||||||
for (const auto& path : paths) {
|
for (const auto& path : paths) {
|
||||||
auto it = _fileMappings.find(path);
|
auto it = _fileMappings.find(path);
|
||||||
if (it != _fileMappings.end()) {
|
if (it != _fileMappings.end()) {
|
||||||
|
auto type = assetTypeForFilename(path);
|
||||||
|
if (type == Undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString bakedFilename = bakedFilenameForAssetType(type);
|
||||||
|
|
||||||
auto hash = it->second;
|
auto hash = it->second;
|
||||||
|
|
||||||
auto dotIndex = path.lastIndexOf(".");
|
|
||||||
if (dotIndex == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto extension = path.mid(dotIndex + 1);
|
|
||||||
|
|
||||||
QString bakedFilename;
|
|
||||||
|
|
||||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(extension)) {
|
|
||||||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
|
||||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
|
|
||||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
|
||||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
|
||||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bakedMapping = getBakeMapping(hash, bakedFilename);
|
auto bakedMapping = getBakeMapping(hash, bakedFilename);
|
||||||
|
|
||||||
auto it = _fileMappings.find(bakedMapping);
|
auto it = _fileMappings.find(bakedMapping);
|
||||||
|
|
|
@ -23,8 +23,47 @@
|
||||||
|
|
||||||
#include "RegisteredMetaTypes.h"
|
#include "RegisteredMetaTypes.h"
|
||||||
|
|
||||||
|
using BakeVersion = int;
|
||||||
|
static const BakeVersion INITIAL_BAKE_VERSION = 0;
|
||||||
|
static const BakeVersion NEEDS_BAKING_BAKE_VERSION = -1;
|
||||||
|
|
||||||
|
enum BakedAssetType : int {
|
||||||
|
Model = 0,
|
||||||
|
Texture,
|
||||||
|
Script,
|
||||||
|
|
||||||
|
NUM_ASSET_TYPES,
|
||||||
|
Undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
// ATTENTION! If you change the current version for an asset type, you will also
|
||||||
|
// need to update the function currentBakeVersionForAssetType() inside of AssetServer.cpp.
|
||||||
|
enum class ModelBakeVersion : BakeVersion {
|
||||||
|
Initial = INITIAL_BAKE_VERSION,
|
||||||
|
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// ATTENTION! See above.
|
||||||
|
enum class TextureBakeVersion : BakeVersion {
|
||||||
|
Initial = INITIAL_BAKE_VERSION,
|
||||||
|
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// ATTENTION! See above.
|
||||||
|
enum class ScriptBakeVersion : BakeVersion {
|
||||||
|
Initial = INITIAL_BAKE_VERSION,
|
||||||
|
FixEmptyScripts,
|
||||||
|
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
struct AssetMeta {
|
struct AssetMeta {
|
||||||
int bakeVersion { 0 };
|
AssetMeta() {
|
||||||
|
}
|
||||||
|
|
||||||
|
BakeVersion bakeVersion;
|
||||||
bool failedLastBake { false };
|
bool failedLastBake { false };
|
||||||
QString lastBakeErrors;
|
QString lastBakeErrors;
|
||||||
};
|
};
|
||||||
|
|
16
interface/resources/icons/+android/stats.svg
Normal file
16
interface/resources/icons/+android/stats.svg
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||||
|
<path d="M45,40.3l-7.1-6.3c-0.7-0.7-1.7-0.9-2.6-0.8c2.3-2.9,3.6-6.4,3.6-10.3c0-9.9-7.9-17-16.9-17.1c-9.3,0-16.7,7.4-17,16.3
|
||||||
|
C4.7,32,12.6,39.6,21.9,39.7c4.2,0,8.1-1.5,11-4.1c-0.2,0.9,0.1,1.9,0.9,2.6l7.1,6.3c1.2,1.1,3,1.1,4.1-0.1c0.5-0.6,0.8-1.3,0.8-2
|
||||||
|
C45.9,41.6,45.6,40.8,45,40.3z M22.5,35.4c-7.3,0.3-13.2-5.5-13.2-12.8C9.2,15.8,14.9,10.1,21.9,10c7-0.1,12.8,5.6,12.8,12.7
|
||||||
|
C34.7,29.7,29.2,35.2,22.5,35.4z"/>
|
||||||
|
<path d="M26.2,19.9c-0.5,1.2-0.9,2.4-1.3,3.5c-0.6,1.6-1.2,3.2-1.8,4.8c-0.3,0.8-0.8,1.2-1.6,1.2c-0.8,0-1.2-0.3-1.6-1.2
|
||||||
|
c-0.9-2.1-1.8-4.2-2.6-6.2c0-0.1-0.1-0.2-0.2-0.5c-0.3,0.5-0.6,0.9-0.8,1.4c-0.4,0.9-1.1,1.3-2.1,1.2c-0.6,0-1.2,0-1.8,0
|
||||||
|
c-0.9,0-1.5-0.6-1.5-1.4c-0.1-0.7,0.5-1.4,1.3-1.5c0.2,0,0.4-0.1,0.5-0.1c0.7,0.1,1.1-0.2,1.5-0.9c0.5-1,1.1-2,1.6-3
|
||||||
|
c0.3-0.6,0.8-1,1.6-1c0.7,0,1.2,0.5,1.5,1.1c0.8,1.8,1.6,3.7,2.3,5.5c0.1,0.2,0.1,0.3,0.3,0.6c0.2-0.6,0.4-1.1,0.6-1.6
|
||||||
|
c0.9-2.4,1.8-4.8,2.7-7.2c0.3-0.9,0.8-1.2,1.5-1.2c0.8,0,1.3,0.4,1.6,1.2c0.7,1.8,1.3,3.6,1.9,5.5c0.4,1,0.1,0.8,1.1,0.8
|
||||||
|
c0.4,0,0.8,0,1.1,0.1c0.7,0.2,1.2,0.8,1.1,1.6c-0.1,0.7-0.6,1.3-1.4,1.3c-1,0-2,0-3,0c-0.7,0-1.1-0.4-1.4-1.1
|
||||||
|
C27,22.1,26.6,21.1,26.2,19.9z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
9
interface/resources/qml/+android/StatText.qml
Normal file
9
interface/resources/qml/+android/StatText.qml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: "white";
|
||||||
|
style: Text.Outline;
|
||||||
|
styleColor: "black";
|
||||||
|
font.pixelSize: 15;
|
||||||
|
}
|
|
@ -163,8 +163,10 @@ TextField {
|
||||||
text: textField.label
|
text: textField.label
|
||||||
colorScheme: textField.colorScheme
|
colorScheme: textField.colorScheme
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
anchors.bottom: parent.top
|
anchors.bottom: parent.top
|
||||||
anchors.bottomMargin: 3
|
anchors.bottomMargin: 3
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
visible: label != ""
|
visible: label != ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,34 +65,33 @@ TabletModalWindow {
|
||||||
id: modalWindowItem
|
id: modalWindowItem
|
||||||
width: parent.width - 12
|
width: parent.width - 12
|
||||||
height: 240
|
height: 240
|
||||||
anchors {
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
readonly property int minWidth: 470
|
readonly property int minWidth: modalWindowItem.width
|
||||||
readonly property int maxWidth: 470
|
readonly property int maxWidth: modalWindowItem.width
|
||||||
readonly property int minHeight: 120
|
readonly property int minHeight: 120
|
||||||
readonly property int maxHeight: 720
|
readonly property int maxHeight: 720
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
var targetWidth = Math.max(titleWidth, 470)
|
var targetWidth = Math.max(titleWidth, modalWindowItem.width)
|
||||||
var targetHeight = (items ? comboBox.controlHeight : textResult.controlHeight) + 5 * hifi.dimensions.contentSpacing.y + buttons.height
|
var targetHeight = (items ? comboBox.controlHeight : textResult.controlHeight) + 5 * hifi.dimensions.contentSpacing.y + buttons.height
|
||||||
modalWindowItem.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
modalWindowItem.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
||||||
modalWindowItem.height = ((targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)) + ((keyboardEnabled && keyboardRaised) ? (keyboard.raisedHeight + 2 * hifi.dimensions.contentSpacing.y) : 0) + modalWindowItem.frameMarginTop
|
modalWindowItem.height = ((targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)) + modalWindowItem.frameMarginTop
|
||||||
|
modalWindowItem.y = (root.height - (modalWindowItem.height + ((keyboardEnabled && keyboardRaised) ? (keyboard.raisedHeight + 2 * hifi.dimensions.contentSpacing.y) : 0))) / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors {
|
anchors {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
bottom: keyboard.top;
|
bottom: buttons.top;
|
||||||
left: parent.left;
|
left: parent.left;
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
margins: 0
|
margins: 0
|
||||||
bottomMargin: 2 * hifi.dimensions.contentSpacing.y
|
bottomMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||||
|
topMargin: modalWindowItem.frameMarginTop
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||||
|
@ -106,6 +105,7 @@ TabletModalWindow {
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
leftMargin: 5
|
leftMargin: 5
|
||||||
|
rightMargin: 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,22 +124,6 @@ TabletModalWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property alias keyboardOverride: root.keyboardOverride
|
|
||||||
property alias keyboardRaised: root.keyboardRaised
|
|
||||||
property alias punctuationMode: root.punctuationMode
|
|
||||||
|
|
||||||
Keyboard {
|
|
||||||
id: keyboard
|
|
||||||
raised: keyboardEnabled && keyboardRaised
|
|
||||||
numeric: punctuationMode
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
bottom: buttons.top
|
|
||||||
bottomMargin: raised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
id: buttons
|
id: buttons
|
||||||
focus: true
|
focus: true
|
||||||
|
@ -150,6 +134,7 @@ TabletModalWindow {
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
right: parent.right
|
right: parent.right
|
||||||
margins: 0
|
margins: 0
|
||||||
|
rightMargin: hifi.dimensions.borderRadius
|
||||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||||
}
|
}
|
||||||
Button { action: cancelAction }
|
Button { action: cancelAction }
|
||||||
|
@ -177,7 +162,17 @@ TabletModalWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keyboard {
|
||||||
|
id: keyboard
|
||||||
|
raised: keyboardEnabled && keyboardRaised
|
||||||
|
numeric: punctuationMode
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: modalWindowItem.bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Keys.onPressed: {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
71
interface/resources/qml/hifi/+android/StatsBar.qml
Normal file
71
interface/resources/qml/hifi/+android/StatsBar.qml
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
import "../../styles-uit"
|
||||||
|
import "../../controls-uit" as HifiControlsUit
|
||||||
|
import "../../controls" as HifiControls
|
||||||
|
import ".."
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: bar
|
||||||
|
x:300
|
||||||
|
y:0
|
||||||
|
width: 300
|
||||||
|
height: 300
|
||||||
|
z: -1
|
||||||
|
|
||||||
|
signal sendToScript(var message);
|
||||||
|
signal windowClosed();
|
||||||
|
|
||||||
|
property bool shown: true
|
||||||
|
|
||||||
|
onShownChanged: {
|
||||||
|
bar.visible = shown;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill : parent
|
||||||
|
color: "transparent"
|
||||||
|
Flow {
|
||||||
|
id: flowMain
|
||||||
|
spacing: 10
|
||||||
|
flow: Flow.TopToBottom
|
||||||
|
layoutDirection: Flow.TopToBottom
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
// put on bottom
|
||||||
|
x = 300;
|
||||||
|
y = 0;
|
||||||
|
width = 300;
|
||||||
|
height = 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addButton(properties) {
|
||||||
|
var component = Qt.createComponent("button.qml");
|
||||||
|
if (component.status == Component.Ready) {
|
||||||
|
var button = component.createObject(flowMain);
|
||||||
|
// copy all properites to button
|
||||||
|
var keys = Object.keys(properties).forEach(function (key) {
|
||||||
|
button[key] = properties[key];
|
||||||
|
});
|
||||||
|
return button;
|
||||||
|
} else if( component.status == Component.Error) {
|
||||||
|
console.log("Load button errors " + component.errorString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function urlHelper(src) {
|
||||||
|
if (src.match(/\bhttp/)) {
|
||||||
|
return src;
|
||||||
|
} else {
|
||||||
|
return "../../../" + src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -69,11 +69,11 @@ void AssetMappingsScriptingInterface::getMapping(QString path, QJSValue callback
|
||||||
|
|
||||||
void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping, QJSValue startedCallback, QJSValue completedCallback, bool dropEvent) {
|
void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping, QJSValue startedCallback, QJSValue completedCallback, bool dropEvent) {
|
||||||
static const QString helpText =
|
static const QString helpText =
|
||||||
"Upload your asset to a specific folder by entering the full path. Specifying\n"
|
"Upload your asset to a specific folder by entering the full path. Specifying "
|
||||||
"a new folder name will automatically create that folder for you.";
|
"a new folder name will automatically create that folder for you.";
|
||||||
static const QString dropHelpText =
|
static const QString dropHelpText =
|
||||||
"This file will be added to your Asset Server.\n"
|
"This file will be added to your Asset Server.\n"
|
||||||
"Use the field below to place your file in a specific folder or to rename it.\n"
|
"Use the field below to place your file in a specific folder or to rename it. "
|
||||||
"Specifying a new folder name will automatically create that folder for you.";
|
"Specifying a new folder name will automatically create that folder for you.";
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
|
|
@ -882,6 +882,11 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
||||||
|
|
||||||
//virtual
|
//virtual
|
||||||
const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
|
const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
// disable IK on android
|
||||||
|
return underPoses;
|
||||||
|
#endif
|
||||||
|
|
||||||
// allows solutionSource to be overridden by an animVar
|
// allows solutionSource to be overridden by an animVar
|
||||||
auto solutionSource = animVars.lookup(_solutionSourceVar, (int)_solutionSource);
|
auto solutionSource = animVars.lookup(_solutionSourceVar, (int)_solutionSource);
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,8 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) {
|
||||||
|
|
||||||
qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID;
|
qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID;
|
||||||
|
|
||||||
for (const auto& inputMapping : device->getAvailableInputs()) {
|
auto inputs = device->getAvailableInputs();
|
||||||
|
for (const auto& inputMapping : inputs) {
|
||||||
const auto& input = inputMapping.first;
|
const auto& input = inputMapping.first;
|
||||||
// Ignore aliases
|
// Ignore aliases
|
||||||
if (_endpointsByInput.count(input)) {
|
if (_endpointsByInput.count(input)) {
|
||||||
|
@ -126,7 +127,8 @@ void UserInputMapper::removeDevice(int deviceID) {
|
||||||
_mappingsByDevice.erase(mappingsEntry);
|
_mappingsByDevice.erase(mappingsEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& inputMapping : device->getAvailableInputs()) {
|
auto inputs = device->getAvailableInputs();
|
||||||
|
for (const auto& inputMapping : inputs) {
|
||||||
const auto& input = inputMapping.first;
|
const auto& input = inputMapping.first;
|
||||||
auto endpoint = _endpointsByInput.find(input);
|
auto endpoint = _endpointsByInput.find(input);
|
||||||
if (endpoint != _endpointsByInput.end()) {
|
if (endpoint != _endpointsByInput.end()) {
|
||||||
|
@ -171,7 +173,7 @@ InputDevice::Pointer UserInputMapper::getDevice(const Input& input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UserInputMapper::getDeviceName(uint16 deviceID) {
|
QString UserInputMapper::getDeviceName(uint16 deviceID) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
if (_registeredDevices.find(deviceID) != _registeredDevices.end()) {
|
if (_registeredDevices.find(deviceID) != _registeredDevices.end()) {
|
||||||
return _registeredDevices[deviceID]->_name;
|
return _registeredDevices[deviceID]->_name;
|
||||||
|
@ -181,7 +183,7 @@ QString UserInputMapper::getDeviceName(uint16 deviceID) {
|
||||||
|
|
||||||
int UserInputMapper::findDevice(QString name) const {
|
int UserInputMapper::findDevice(QString name) const {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
for (auto device : _registeredDevices) {
|
for (const auto& device : _registeredDevices) {
|
||||||
if (device.second->_name == name) {
|
if (device.second->_name == name) {
|
||||||
return device.first;
|
return device.first;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +194,7 @@ int UserInputMapper::findDevice(QString name) const {
|
||||||
QVector<QString> UserInputMapper::getDeviceNames() {
|
QVector<QString> UserInputMapper::getDeviceNames() {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
QVector<QString> result;
|
QVector<QString> result;
|
||||||
for (auto device : _registeredDevices) {
|
for (const auto& device : _registeredDevices) {
|
||||||
QString deviceName = device.second->_name.split(" (")[0];
|
QString deviceName = device.second->_name.split(" (")[0];
|
||||||
result << deviceName;
|
result << deviceName;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +220,7 @@ Input UserInputMapper::findDeviceInput(const QString& inputName) const {
|
||||||
const auto& device = _registeredDevices.at(deviceID);
|
const auto& device = _registeredDevices.at(deviceID);
|
||||||
auto deviceInputs = device->getAvailableInputs();
|
auto deviceInputs = device->getAvailableInputs();
|
||||||
|
|
||||||
for (auto input : deviceInputs) {
|
for (const auto& input : deviceInputs) {
|
||||||
if (input.second == inputName) {
|
if (input.second == inputName) {
|
||||||
return input.first;
|
return input.first;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +323,8 @@ QVector<Action> UserInputMapper::getAllActions() const {
|
||||||
|
|
||||||
QString UserInputMapper::getActionName(Action action) const {
|
QString UserInputMapper::getActionName(Action action) const {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
for (auto actionPair : getActionInputs()) {
|
auto inputs = getActionInputs();
|
||||||
|
for (const auto& actionPair : inputs) {
|
||||||
if (actionPair.first.channel == toInt(action)) {
|
if (actionPair.first.channel == toInt(action)) {
|
||||||
return actionPair.second;
|
return actionPair.second;
|
||||||
}
|
}
|
||||||
|
@ -331,18 +334,20 @@ QString UserInputMapper::getActionName(Action action) const {
|
||||||
|
|
||||||
QString UserInputMapper::getStandardPoseName(uint16_t pose) {
|
QString UserInputMapper::getStandardPoseName(uint16_t pose) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
for (auto posePair : getStandardInputs()) {
|
auto inputs = getStandardInputs();
|
||||||
|
for (const auto& posePair : inputs) {
|
||||||
if (posePair.first.channel == pose && posePair.first.getType() == ChannelType::POSE) {
|
if (posePair.first.channel == pose && posePair.first.getType() == ChannelType::POSE) {
|
||||||
return posePair.second;
|
return posePair.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QString> UserInputMapper::getActionNames() const {
|
QVector<QString> UserInputMapper::getActionNames() const {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
QVector<QString> result;
|
QVector<QString> result;
|
||||||
for (auto actionPair : getActionInputs()) {
|
auto inputs = getActionInputs();
|
||||||
|
for (const auto& actionPair : inputs) {
|
||||||
result << actionPair.second;
|
result << actionPair.second;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -357,7 +362,7 @@ Pose UserInputMapper::getPoseState(Action action) const {
|
||||||
bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
bool toReturn = false;
|
bool toReturn = false;
|
||||||
for (auto device : _registeredDevices) {
|
for (const auto& device : _registeredDevices) {
|
||||||
toReturn = toReturn || device.second->triggerHapticPulse(strength, duration, hand);
|
toReturn = toReturn || device.second->triggerHapticPulse(strength, duration, hand);
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
|
@ -469,7 +474,7 @@ void UserInputMapper::runMappings() {
|
||||||
if (debugRoutes) {
|
if (debugRoutes) {
|
||||||
qCDebug(controllers) << "Beginning mapping frame";
|
qCDebug(controllers) << "Beginning mapping frame";
|
||||||
}
|
}
|
||||||
for (auto endpointEntry : this->_endpointsByInput) {
|
for (const auto& endpointEntry : _endpointsByInput) {
|
||||||
endpointEntry.second->reset();
|
endpointEntry.second->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,9 +547,9 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Most endpoints can only be read once (though a given mapping can route them to
|
// Most endpoints can only be read once (though a given mapping can route them to
|
||||||
// multiple places). Consider... If the default is to wire the A button to JUMP
|
// multiple places). Consider... If the default is to wire the A button to JUMP
|
||||||
// and someone else wires it to CONTEXT_MENU, I don't want both to occur when
|
// and someone else wires it to CONTEXT_MENU, I don't want both to occur when
|
||||||
// I press the button. The exception is if I'm wiring a control back to itself
|
// I press the button. The exception is if I'm wiring a control back to itself
|
||||||
// in order to adjust my interface, like inverting the Y axis on an analog stick
|
// in order to adjust my interface, like inverting the Y axis on an analog stick
|
||||||
if (!route->peek && !source->readable()) {
|
if (!route->peek && !source->readable()) {
|
||||||
|
@ -897,7 +902,8 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value)
|
||||||
if (value.isArray()) {
|
if (value.isArray()) {
|
||||||
// Support "when" : [ "GamePad.RB", "GamePad.LB" ]
|
// Support "when" : [ "GamePad.RB", "GamePad.LB" ]
|
||||||
Conditional::List children;
|
Conditional::List children;
|
||||||
for (auto arrayItem : value.toArray()) {
|
auto array = value.toArray();
|
||||||
|
for (const auto& arrayItem : array) {
|
||||||
Conditional::Pointer childConditional = parseConditional(arrayItem);
|
Conditional::Pointer childConditional = parseConditional(arrayItem);
|
||||||
if (!childConditional) {
|
if (!childConditional) {
|
||||||
return Conditional::Pointer();
|
return Conditional::Pointer();
|
||||||
|
@ -908,7 +914,7 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value)
|
||||||
} else if (value.isString()) {
|
} else if (value.isString()) {
|
||||||
// Support "when" : "GamePad.RB"
|
// Support "when" : "GamePad.RB"
|
||||||
auto conditionalToken = value.toString();
|
auto conditionalToken = value.toString();
|
||||||
|
|
||||||
// Detect for modifier case (Not...)
|
// Detect for modifier case (Not...)
|
||||||
QString conditionalModifier;
|
QString conditionalModifier;
|
||||||
const QString JSON_CONDITIONAL_MODIFIER_NOT("!");
|
const QString JSON_CONDITIONAL_MODIFIER_NOT("!");
|
||||||
|
@ -943,12 +949,12 @@ Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) {
|
||||||
result = Filter::getFactory().create(value.toString());
|
result = Filter::getFactory().create(value.toString());
|
||||||
} else if (value.isObject()) {
|
} else if (value.isObject()) {
|
||||||
result = Filter::parse(value.toObject());
|
result = Filter::parse(value.toObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
qWarning() << "Invalid filter definition " << value;
|
qWarning() << "Invalid filter definition " << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +966,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
|
||||||
if (value.isArray()) {
|
if (value.isArray()) {
|
||||||
Filter::List result;
|
Filter::List result;
|
||||||
auto filtersArray = value.toArray();
|
auto filtersArray = value.toArray();
|
||||||
for (auto filterValue : filtersArray) {
|
for (const auto& filterValue : filtersArray) {
|
||||||
Filter::Pointer filter = parseFilter(filterValue);
|
Filter::Pointer filter = parseFilter(filterValue);
|
||||||
if (!filter) {
|
if (!filter) {
|
||||||
return Filter::List();
|
return Filter::List();
|
||||||
|
@ -968,7 +974,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
|
||||||
result.push_back(filter);
|
result.push_back(filter);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Filter::Pointer filter = parseFilter(value);
|
Filter::Pointer filter = parseFilter(value);
|
||||||
if (!filter) {
|
if (!filter) {
|
||||||
|
@ -980,7 +986,8 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
|
||||||
Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) {
|
Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) {
|
||||||
if (value.isArray()) {
|
if (value.isArray()) {
|
||||||
ArrayEndpoint::Pointer result = std::make_shared<ArrayEndpoint>();
|
ArrayEndpoint::Pointer result = std::make_shared<ArrayEndpoint>();
|
||||||
for (auto arrayItem : value.toArray()) {
|
auto array = value.toArray();
|
||||||
|
for (const auto& arrayItem : array) {
|
||||||
Endpoint::Pointer destination = parseEndpoint(arrayItem);
|
Endpoint::Pointer destination = parseEndpoint(arrayItem);
|
||||||
if (!destination) {
|
if (!destination) {
|
||||||
return Endpoint::Pointer();
|
return Endpoint::Pointer();
|
||||||
|
@ -988,14 +995,14 @@ Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) {
|
||||||
result->_children.push_back(destination);
|
result->_children.push_back(destination);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseEndpoint(value);
|
return parseEndpoint(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) {
|
Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) {
|
||||||
if (value.isObject()) {
|
if (value.isObject()) {
|
||||||
auto object = value.toObject();
|
auto object = value.toObject();
|
||||||
if (object.contains("makeAxis")) {
|
if (object.contains("makeAxis")) {
|
||||||
auto axisValue = object.value("makeAxis");
|
auto axisValue = object.value("makeAxis");
|
||||||
if (axisValue.isArray()) {
|
if (axisValue.isArray()) {
|
||||||
|
@ -1017,7 +1024,8 @@ Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) {
|
||||||
Endpoint::Pointer UserInputMapper::parseAny(const QJsonValue& value) {
|
Endpoint::Pointer UserInputMapper::parseAny(const QJsonValue& value) {
|
||||||
if (value.isArray()) {
|
if (value.isArray()) {
|
||||||
Endpoint::List children;
|
Endpoint::List children;
|
||||||
for (auto arrayItem : value.toArray()) {
|
auto array = value.toArray();
|
||||||
|
for (const auto& arrayItem : array) {
|
||||||
Endpoint::Pointer destination = parseEndpoint(arrayItem);
|
Endpoint::Pointer destination = parseEndpoint(arrayItem);
|
||||||
if (!destination) {
|
if (!destination) {
|
||||||
return Endpoint::Pointer();
|
return Endpoint::Pointer();
|
||||||
|
@ -1162,7 +1170,7 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool hasDebuggableRoute(const T& routes) {
|
bool hasDebuggableRoute(const T& routes) {
|
||||||
for (auto route : routes) {
|
for (const auto& route : routes) {
|
||||||
if (route->debug) {
|
if (route->debug) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1174,7 +1182,7 @@ bool hasDebuggableRoute(const T& routes) {
|
||||||
void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
// New routes for a device get injected IN FRONT of existing routes. Routes
|
// New routes for a device get injected IN FRONT of existing routes. Routes
|
||||||
// are processed in order so this ensures that the standard -> action processing
|
// are processed in order so this ensures that the standard -> action processing
|
||||||
// takes place after all of the hardware -> standard or hardware -> action processing
|
// takes place after all of the hardware -> standard or hardware -> action processing
|
||||||
// because standard -> action is the first set of routes added.
|
// because standard -> action is the first set of routes added.
|
||||||
Route::List standardRoutes = mapping->routes;
|
Route::List standardRoutes = mapping->routes;
|
||||||
|
|
|
@ -16,11 +16,14 @@
|
||||||
using namespace controller;
|
using namespace controller;
|
||||||
|
|
||||||
void ActionEndpoint::apply(float newValue, const Pointer& source) {
|
void ActionEndpoint::apply(float newValue, const Pointer& source) {
|
||||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||||
if(inputRecorder->isPlayingback()) {
|
QString actionName;
|
||||||
newValue = inputRecorder->getActionState(actionName);
|
if (inputRecorder->isPlayingback() || inputRecorder->isRecording()) {
|
||||||
|
actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||||
|
if (inputRecorder->isPlayingback()) {
|
||||||
|
newValue = inputRecorder->getActionState(actionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentValue += newValue;
|
_currentValue += newValue;
|
||||||
|
@ -32,10 +35,12 @@ void ActionEndpoint::apply(float newValue, const Pointer& source) {
|
||||||
|
|
||||||
void ActionEndpoint::apply(const Pose& value, const Pointer& source) {
|
void ActionEndpoint::apply(const Pose& value, const Pointer& source) {
|
||||||
_currentPose = value;
|
_currentPose = value;
|
||||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||||
inputRecorder->setActionState(actionName, _currentPose);
|
if (inputRecorder->isRecording()) {
|
||||||
|
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||||
|
inputRecorder->setActionState(actionName, _currentPose);
|
||||||
|
}
|
||||||
|
|
||||||
if (!_currentPose.isValid()) {
|
if (!_currentPose.isValid()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -530,7 +530,11 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur
|
||||||
batch.setStateScissorRect(scissor);
|
batch.setStateScissorRect(scissor);
|
||||||
batch.setViewportTransform(viewport);
|
batch.setViewportTransform(viewport);
|
||||||
batch.setResourceTexture(0, texture);
|
batch.setResourceTexture(0, texture);
|
||||||
|
#ifndef USE_GLES
|
||||||
batch.setPipeline(_presentPipeline);
|
batch.setPipeline(_presentPipeline);
|
||||||
|
#else
|
||||||
|
batch.setPipeline(_simplePipeline);
|
||||||
|
#endif
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
if (copyFbo) {
|
if (copyFbo) {
|
||||||
gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight());
|
gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight());
|
||||||
|
|
|
@ -451,8 +451,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||||
* @property {Entities.EntityType} type - The entity type. You cannot change the type of an entity after it's created. (Though
|
* @property {Entities.EntityType} type - The entity type. You cannot change the type of an entity after it's created. (Though
|
||||||
* its value may switch among <code>"Box"</code>, <code>"Shape"</code>, and <code>"Sphere"</code> depending on changes to
|
* its value may switch among <code>"Box"</code>, <code>"Shape"</code>, and <code>"Sphere"</code> depending on changes to
|
||||||
* the <code>shape</code> property set for entities of these types.) <em>Read-only.</em>
|
* the <code>shape</code> property set for entities of these types.) <em>Read-only.</em>
|
||||||
* @property {boolean} clientOnly=false - If <code>true</code> then the entity is an avatar entity, otherwise it is a server
|
* @property {boolean} clientOnly=false - If <code>true</code> then the entity is an avatar entity; otherwise it is a server
|
||||||
* entity. <em>Read-only.</em>
|
* entity. An avatar entity follows you to each domain you visit, rendering at the same world coordinates unless it's
|
||||||
|
* parented to your avatar. <em>Value cannot be changed after the entity is created.</em><br />
|
||||||
|
* The value can also be set at entity creation by using the <code>clientOnly</code> parameter in
|
||||||
|
* {@link Entities.addEntity}.
|
||||||
* @property {Uuid} owningAvatarID=Uuid.NULL - The session ID of the owning avatar if <code>clientOnly</code> is
|
* @property {Uuid} owningAvatarID=Uuid.NULL - The session ID of the owning avatar if <code>clientOnly</code> is
|
||||||
* <code>true</code>, otherwise {@link Uuid|Uuid.NULL}. <em>Read-only.</em>
|
* <code>true</code>, otherwise {@link Uuid|Uuid.NULL}. <em>Read-only.</em>
|
||||||
*
|
*
|
||||||
|
@ -1413,7 +1416,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_DIMENSIONS, localDimensions);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_DIMENSIONS, localDimensions);
|
||||||
|
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLIENT_ONLY, clientOnly); // Gettable but not settable
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLIENT_ONLY, clientOnly); // Gettable but not settable except at entity creation
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable
|
||||||
|
|
||||||
// Rendering info
|
// Rendering info
|
||||||
|
|
|
@ -203,9 +203,9 @@ public slots:
|
||||||
* Add a new entity with specified properties.
|
* Add a new entity with specified properties.
|
||||||
* @function Entities.addEntity
|
* @function Entities.addEntity
|
||||||
* @param {Entities.EntityProperties} properties - The properties of the entity to create.
|
* @param {Entities.EntityProperties} properties - The properties of the entity to create.
|
||||||
* @param {boolean} [clientOnly=false] - If <code>true</code>, the entity is created as an avatar entity, otherwise it
|
* @param {boolean} [clientOnly=false] - If <code>true</code>, or if <code>clientOnly</code> is set <code>true</code> in
|
||||||
* is created on the server. An avatar entity follows you to each domain you visit, rendering at the same world
|
* the properties, the entity is created as an avatar entity; otherwise it is created on the server. An avatar entity
|
||||||
* coordinates unless it's parented to your avatar.
|
* follows you to each domain you visit, rendering at the same world coordinates unless it's parented to your avatar.
|
||||||
* @returns {Uuid} The ID of the entity if successfully created, otherwise {@link Uuid|Uuid.NULL}.
|
* @returns {Uuid} The ID of the entity if successfully created, otherwise {@link Uuid|Uuid.NULL}.
|
||||||
* @example <caption>Create a box entity in front of your avatar.</caption>
|
* @example <caption>Create a box entity in front of your avatar.</caption>
|
||||||
* var entityID = Entities.addEntity({
|
* var entityID = Entities.addEntity({
|
||||||
|
|
|
@ -16,7 +16,8 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
||||||
"system/+android/touchscreenvirtualpad.js",
|
"system/+android/touchscreenvirtualpad.js",
|
||||||
"system/+android/bottombar.js",
|
"system/+android/bottombar.js",
|
||||||
"system/+android/audio.js" ,
|
"system/+android/audio.js" ,
|
||||||
"system/+android/modes.js"/*,
|
"system/+android/modes.js",
|
||||||
|
"system/+android/stats.js"/*,
|
||||||
"system/away.js",
|
"system/away.js",
|
||||||
"system/controllers/controllerDisplayManager.js",
|
"system/controllers/controllerDisplayManager.js",
|
||||||
"system/controllers/handControllerGrabAndroid.js",
|
"system/controllers/handControllerGrabAndroid.js",
|
||||||
|
|
39
scripts/system/+android/stats.js
Normal file
39
scripts/system/+android/stats.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
"use strict";
|
||||||
|
//
|
||||||
|
// stats.js
|
||||||
|
// scripts/system/
|
||||||
|
//
|
||||||
|
// Created by Sam Gondelman on 3/14/18
|
||||||
|
// Copyright 2018 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
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
|
|
||||||
|
var statsbar;
|
||||||
|
var statsButton;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
statsbar = new QmlFragment({
|
||||||
|
qml: "hifi/StatsBar.qml"
|
||||||
|
});
|
||||||
|
|
||||||
|
statsButton = statsbar.addButton({
|
||||||
|
icon: "icons/stats.svg",
|
||||||
|
activeIcon: "icons/stats.svg",
|
||||||
|
textSize: 45,
|
||||||
|
bgOpacity: 0.0,
|
||||||
|
activeBgOpacity: 0.0,
|
||||||
|
bgColor: "#FFFFFF",
|
||||||
|
text: "STATS"
|
||||||
|
});
|
||||||
|
statsButton.clicked.connect(function() {
|
||||||
|
Menu.triggerOption("Stats");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
}()); // END LOCAL_SCOPE
|
|
@ -18,6 +18,7 @@
|
||||||
#include "ModelBakingLoggingCategory.h"
|
#include "ModelBakingLoggingCategory.h"
|
||||||
#include "BakerCLI.h"
|
#include "BakerCLI.h"
|
||||||
#include "FBXBaker.h"
|
#include "FBXBaker.h"
|
||||||
|
#include "JSBaker.h"
|
||||||
#include "TextureBaker.h"
|
#include "TextureBaker.h"
|
||||||
|
|
||||||
BakerCLI::BakerCLI(OvenCLIApplication* parent) : QObject(parent) {
|
BakerCLI::BakerCLI(OvenCLIApplication* parent) : QObject(parent) {
|
||||||
|
@ -34,6 +35,7 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString&
|
||||||
qDebug() << "Baking file type: " << type;
|
qDebug() << "Baking file type: " << type;
|
||||||
|
|
||||||
static const QString MODEL_EXTENSION { "fbx" };
|
static const QString MODEL_EXTENSION { "fbx" };
|
||||||
|
static const QString SCRIPT_EXTENSION { "js" };
|
||||||
|
|
||||||
QString extension = type;
|
QString extension = type;
|
||||||
|
|
||||||
|
@ -44,6 +46,7 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString&
|
||||||
|
|
||||||
// check what kind of baker we should be creating
|
// check what kind of baker we should be creating
|
||||||
bool isFBX = extension == MODEL_EXTENSION;
|
bool isFBX = extension == MODEL_EXTENSION;
|
||||||
|
bool isScript = extension == SCRIPT_EXTENSION;
|
||||||
|
|
||||||
bool isSupportedImage = QImageReader::supportedImageFormats().contains(extension.toLatin1());
|
bool isSupportedImage = QImageReader::supportedImageFormats().contains(extension.toLatin1());
|
||||||
|
|
||||||
|
@ -57,12 +60,16 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString&
|
||||||
outputPath)
|
outputPath)
|
||||||
};
|
};
|
||||||
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
|
} else if (isScript) {
|
||||||
|
_baker = std::unique_ptr<Baker> { new JSBaker(inputUrl, outputPath) };
|
||||||
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
} else if (isSupportedImage) {
|
} else if (isSupportedImage) {
|
||||||
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) };
|
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) };
|
||||||
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
} else {
|
} else {
|
||||||
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
||||||
QCoreApplication::exit(OVEN_STATUS_CODE_FAIL);
|
QCoreApplication::exit(OVEN_STATUS_CODE_FAIL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// invoke the bake method on the baker thread
|
// invoke the bake method on the baker thread
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -31,6 +32,8 @@ class BakerCLI : public QObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BakerCLI(OvenCLIApplication* parent);
|
BakerCLI(OvenCLIApplication* parent);
|
||||||
|
|
||||||
|
public slots:
|
||||||
void bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type = QString::null);
|
void bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type = QString::null);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -40,7 +40,8 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
||||||
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
||||||
QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)));
|
QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)));
|
||||||
QString type = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null;
|
QString type = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null;
|
||||||
cli->bakeFile(inputUrl, outputUrl.toString(), type);
|
QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl),
|
||||||
|
Q_ARG(QString, outputUrl.toString()), Q_ARG(QString, type));
|
||||||
} else {
|
} else {
|
||||||
parser.showHelp();
|
parser.showHelp();
|
||||||
QCoreApplication::quit();
|
QCoreApplication::quit();
|
||||||
|
|
Loading…
Reference in a new issue