mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 10:13:22 +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
assignment-client/src/assets
interface
resources
icons/+android
qml
src/scripting
libraries
animation/src
controllers/src/controllers
display-plugins/src/display-plugins
entities/src
scripts
tools/oven/src
|
@ -46,15 +46,68 @@ static const uint8_t CPU_AFFINITY_COUNT_LOW = 1;
|
|||
static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
||||
#endif
|
||||
|
||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||
|
||||
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
||||
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_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
||||
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) {
|
||||
qDebug() << "Starting bake for: " << assetPath << assetHash;
|
||||
auto it = _pendingBakes.find(assetHash);
|
||||
|
@ -167,36 +220,38 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU
|
|||
return false;
|
||||
}
|
||||
|
||||
auto dotIndex = path.lastIndexOf(".");
|
||||
if (dotIndex == -1) {
|
||||
BakedAssetType type = assetTypeForFilename(path);
|
||||
|
||||
if (type == Undefined) {
|
||||
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;
|
||||
AssetMeta meta;
|
||||
std::tie(loaded, meta) = readMetaFile(assetHash);
|
||||
|
||||
// TODO: Allow failed bakes that happened on old versions to be re-baked
|
||||
if (loaded && meta.failedLastBake) {
|
||||
if (type == Texture && !loaded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (loaded && BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit())) {
|
||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
} else {
|
||||
auto currentVersion = currentBakeVersionForAssetType(type);
|
||||
|
||||
if (loaded && (meta.failedLastBake && meta.bakeVersion >= currentVersion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + assetHash + "/" + bakedFilename;
|
||||
return _fileMappings.find(bakedPath) == _fileMappings.end();
|
||||
return !bakedMappingExists || (meta.bakeVersion < currentVersion);
|
||||
}
|
||||
|
||||
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
|
||||
auto assetPathExtension = assetPath.mid(assetPath.lastIndexOf('.') + 1).toLower();
|
||||
QString bakedRootFile;
|
||||
|
||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(assetPathExtension)) {
|
||||
bakedRootFile = BAKED_MODEL_SIMPLE_NAME;
|
||||
} 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 type = assetTypeForFilename(assetPath);
|
||||
QString bakedRootFile = bakedFilenameForAssetType(type);
|
||||
|
||||
auto originalAssetHash = it->second;
|
||||
QString redirectedAssetHash;
|
||||
|
@ -653,9 +702,19 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi
|
|||
auto query = QUrlQuery(url.query());
|
||||
bool isSkybox = query.hasQueryItem("skybox");
|
||||
if (isSkybox) {
|
||||
writeMetaFile(originalAssetHash);
|
||||
if (!bakingDisabled) {
|
||||
maybeBake(assetPath, originalAssetHash);
|
||||
bool loaded;
|
||||
AssetMeta meta;
|
||||
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) {
|
||||
qDebug() << "Failed: " << originalAssetHash << assetPath << errors;
|
||||
qDebug() << "Failed to bake: " << originalAssetHash << assetPath << "(" << errors << ")";
|
||||
|
||||
bool loaded;
|
||||
AssetMeta meta;
|
||||
|
||||
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
|
||||
|
||||
auto type = assetTypeForFilename(assetPath);
|
||||
auto currentTypeVersion = currentBakeVersionForAssetType(type);
|
||||
|
||||
meta.failedLastBake = true;
|
||||
meta.lastBakeErrors = errors;
|
||||
meta.bakeVersion = currentTypeVersion;
|
||||
|
||||
writeMetaFile(originalAssetHash, meta);
|
||||
|
||||
|
@ -1373,17 +1436,20 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina
|
|||
qWarning() << "Failed to remove temporary directory:" << bakedTempOutputDir;
|
||||
}
|
||||
|
||||
if (!errorCompletingBake) {
|
||||
// create the meta file to store which version of the baking process we just completed
|
||||
writeMetaFile(originalAssetHash);
|
||||
} else {
|
||||
auto type = assetTypeForFilename(originalAssetPath);
|
||||
auto currentTypeVersion = currentBakeVersionForAssetType(type);
|
||||
|
||||
AssetMeta meta;
|
||||
meta.bakeVersion = currentTypeVersion;
|
||||
meta.failedLastBake = errorCompletingBake;
|
||||
|
||||
if (errorCompletingBake) {
|
||||
qWarning() << "Could not complete bake for" << originalAssetHash;
|
||||
AssetMeta meta;
|
||||
meta.failedLastBake = true;
|
||||
meta.lastBakeErrors = errorReason;
|
||||
writeMetaFile(originalAssetHash, meta);
|
||||
}
|
||||
|
||||
writeMetaFile(originalAssetHash, meta);
|
||||
|
||||
_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
|
||||
QJsonObject metaFileObject;
|
||||
|
||||
metaFileObject[BAKE_VERSION_KEY] = meta.bakeVersion;
|
||||
metaFileObject[BAKE_VERSION_KEY] = (int)meta.bakeVersion;
|
||||
metaFileObject[FAILED_LAST_BAKE_KEY] = meta.failedLastBake;
|
||||
metaFileObject[LAST_BAKE_ERRORS_KEY] = meta.lastBakeErrors;
|
||||
|
||||
|
@ -1479,27 +1545,13 @@ bool AssetServer::setBakingEnabled(const AssetUtils::AssetPathList& paths, bool
|
|||
for (const auto& path : paths) {
|
||||
auto it = _fileMappings.find(path);
|
||||
if (it != _fileMappings.end()) {
|
||||
auto type = assetTypeForFilename(path);
|
||||
if (type == Undefined) {
|
||||
continue;
|
||||
}
|
||||
QString bakedFilename = bakedFilenameForAssetType(type);
|
||||
|
||||
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 it = _fileMappings.find(bakedMapping);
|
||||
|
|
|
@ -23,8 +23,47 @@
|
|||
|
||||
#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 {
|
||||
int bakeVersion { 0 };
|
||||
AssetMeta() {
|
||||
}
|
||||
|
||||
BakeVersion bakeVersion;
|
||||
bool failedLastBake { false };
|
||||
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 (image error) 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
|
||||
colorScheme: textField.colorScheme
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: 3
|
||||
wrapMode: Text.WordWrap
|
||||
visible: label != ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,34 +65,33 @@ TabletModalWindow {
|
|||
id: modalWindowItem
|
||||
width: parent.width - 12
|
||||
height: 240
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 470
|
||||
readonly property int maxWidth: 470
|
||||
readonly property int minWidth: modalWindowItem.width
|
||||
readonly property int maxWidth: modalWindowItem.width
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
|
||||
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
|
||||
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 {
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: keyboard.top;
|
||||
bottom: buttons.top;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
margins: 0
|
||||
bottomMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
topMargin: modalWindowItem.frameMarginTop
|
||||
}
|
||||
|
||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||
|
@ -106,6 +105,7 @@ TabletModalWindow {
|
|||
right: parent.right;
|
||||
bottom: parent.bottom
|
||||
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 {
|
||||
id: buttons
|
||||
focus: true
|
||||
|
@ -150,6 +134,7 @@ TabletModalWindow {
|
|||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
margins: 0
|
||||
rightMargin: hifi.dimensions.borderRadius
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
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.";
|
||||
static const QString dropHelpText =
|
||||
"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.";
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
|
|
@ -882,6 +882,11 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
|||
|
||||
//virtual
|
||||
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
|
||||
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;
|
||||
|
||||
for (const auto& inputMapping : device->getAvailableInputs()) {
|
||||
auto inputs = device->getAvailableInputs();
|
||||
for (const auto& inputMapping : inputs) {
|
||||
const auto& input = inputMapping.first;
|
||||
// Ignore aliases
|
||||
if (_endpointsByInput.count(input)) {
|
||||
|
@ -126,7 +127,8 @@ void UserInputMapper::removeDevice(int deviceID) {
|
|||
_mappingsByDevice.erase(mappingsEntry);
|
||||
}
|
||||
|
||||
for (const auto& inputMapping : device->getAvailableInputs()) {
|
||||
auto inputs = device->getAvailableInputs();
|
||||
for (const auto& inputMapping : inputs) {
|
||||
const auto& input = inputMapping.first;
|
||||
auto endpoint = _endpointsByInput.find(input);
|
||||
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);
|
||||
if (_registeredDevices.find(deviceID) != _registeredDevices.end()) {
|
||||
return _registeredDevices[deviceID]->_name;
|
||||
|
@ -181,7 +183,7 @@ QString UserInputMapper::getDeviceName(uint16 deviceID) {
|
|||
|
||||
int UserInputMapper::findDevice(QString name) const {
|
||||
Locker locker(_lock);
|
||||
for (auto device : _registeredDevices) {
|
||||
for (const auto& device : _registeredDevices) {
|
||||
if (device.second->_name == name) {
|
||||
return device.first;
|
||||
}
|
||||
|
@ -192,7 +194,7 @@ int UserInputMapper::findDevice(QString name) const {
|
|||
QVector<QString> UserInputMapper::getDeviceNames() {
|
||||
Locker locker(_lock);
|
||||
QVector<QString> result;
|
||||
for (auto device : _registeredDevices) {
|
||||
for (const auto& device : _registeredDevices) {
|
||||
QString deviceName = device.second->_name.split(" (")[0];
|
||||
result << deviceName;
|
||||
}
|
||||
|
@ -218,7 +220,7 @@ Input UserInputMapper::findDeviceInput(const QString& inputName) const {
|
|||
const auto& device = _registeredDevices.at(deviceID);
|
||||
auto deviceInputs = device->getAvailableInputs();
|
||||
|
||||
for (auto input : deviceInputs) {
|
||||
for (const auto& input : deviceInputs) {
|
||||
if (input.second == inputName) {
|
||||
return input.first;
|
||||
}
|
||||
|
@ -321,7 +323,8 @@ QVector<Action> UserInputMapper::getAllActions() const {
|
|||
|
||||
QString UserInputMapper::getActionName(Action action) const {
|
||||
Locker locker(_lock);
|
||||
for (auto actionPair : getActionInputs()) {
|
||||
auto inputs = getActionInputs();
|
||||
for (const auto& actionPair : inputs) {
|
||||
if (actionPair.first.channel == toInt(action)) {
|
||||
return actionPair.second;
|
||||
}
|
||||
|
@ -331,18 +334,20 @@ QString UserInputMapper::getActionName(Action action) const {
|
|||
|
||||
QString UserInputMapper::getStandardPoseName(uint16_t pose) {
|
||||
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) {
|
||||
return posePair.second;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QString> UserInputMapper::getActionNames() const {
|
||||
Locker locker(_lock);
|
||||
QVector<QString> result;
|
||||
for (auto actionPair : getActionInputs()) {
|
||||
auto inputs = getActionInputs();
|
||||
for (const auto& actionPair : inputs) {
|
||||
result << actionPair.second;
|
||||
}
|
||||
return result;
|
||||
|
@ -357,7 +362,7 @@ Pose UserInputMapper::getPoseState(Action action) const {
|
|||
bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||
Locker locker(_lock);
|
||||
bool toReturn = false;
|
||||
for (auto device : _registeredDevices) {
|
||||
for (const auto& device : _registeredDevices) {
|
||||
toReturn = toReturn || device.second->triggerHapticPulse(strength, duration, hand);
|
||||
}
|
||||
return toReturn;
|
||||
|
@ -469,7 +474,7 @@ void UserInputMapper::runMappings() {
|
|||
if (debugRoutes) {
|
||||
qCDebug(controllers) << "Beginning mapping frame";
|
||||
}
|
||||
for (auto endpointEntry : this->_endpointsByInput) {
|
||||
for (const auto& endpointEntry : _endpointsByInput) {
|
||||
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
|
||||
// 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
|
||||
// in order to adjust my interface, like inverting the Y axis on an analog stick
|
||||
if (!route->peek && !source->readable()) {
|
||||
|
@ -897,7 +902,8 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value)
|
|||
if (value.isArray()) {
|
||||
// Support "when" : [ "GamePad.RB", "GamePad.LB" ]
|
||||
Conditional::List children;
|
||||
for (auto arrayItem : value.toArray()) {
|
||||
auto array = value.toArray();
|
||||
for (const auto& arrayItem : array) {
|
||||
Conditional::Pointer childConditional = parseConditional(arrayItem);
|
||||
if (!childConditional) {
|
||||
return Conditional::Pointer();
|
||||
|
@ -908,7 +914,7 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value)
|
|||
} else if (value.isString()) {
|
||||
// Support "when" : "GamePad.RB"
|
||||
auto conditionalToken = value.toString();
|
||||
|
||||
|
||||
// Detect for modifier case (Not...)
|
||||
QString conditionalModifier;
|
||||
const QString JSON_CONDITIONAL_MODIFIER_NOT("!");
|
||||
|
@ -943,12 +949,12 @@ Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) {
|
|||
result = Filter::getFactory().create(value.toString());
|
||||
} else if (value.isObject()) {
|
||||
result = Filter::parse(value.toObject());
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
qWarning() << "Invalid filter definition " << value;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -960,7 +966,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
|
|||
if (value.isArray()) {
|
||||
Filter::List result;
|
||||
auto filtersArray = value.toArray();
|
||||
for (auto filterValue : filtersArray) {
|
||||
for (const auto& filterValue : filtersArray) {
|
||||
Filter::Pointer filter = parseFilter(filterValue);
|
||||
if (!filter) {
|
||||
return Filter::List();
|
||||
|
@ -968,7 +974,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
|
|||
result.push_back(filter);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Filter::Pointer filter = parseFilter(value);
|
||||
if (!filter) {
|
||||
|
@ -980,7 +986,8 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
|
|||
Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) {
|
||||
if (value.isArray()) {
|
||||
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);
|
||||
if (!destination) {
|
||||
return Endpoint::Pointer();
|
||||
|
@ -988,14 +995,14 @@ Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) {
|
|||
result->_children.push_back(destination);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return parseEndpoint(value);
|
||||
}
|
||||
|
||||
Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) {
|
||||
if (value.isObject()) {
|
||||
auto object = value.toObject();
|
||||
auto object = value.toObject();
|
||||
if (object.contains("makeAxis")) {
|
||||
auto axisValue = object.value("makeAxis");
|
||||
if (axisValue.isArray()) {
|
||||
|
@ -1017,7 +1024,8 @@ Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) {
|
|||
Endpoint::Pointer UserInputMapper::parseAny(const QJsonValue& value) {
|
||||
if (value.isArray()) {
|
||||
Endpoint::List children;
|
||||
for (auto arrayItem : value.toArray()) {
|
||||
auto array = value.toArray();
|
||||
for (const auto& arrayItem : array) {
|
||||
Endpoint::Pointer destination = parseEndpoint(arrayItem);
|
||||
if (!destination) {
|
||||
return Endpoint::Pointer();
|
||||
|
@ -1162,7 +1170,7 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) {
|
|||
|
||||
template <typename T>
|
||||
bool hasDebuggableRoute(const T& routes) {
|
||||
for (auto route : routes) {
|
||||
for (const auto& route : routes) {
|
||||
if (route->debug) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1174,7 +1182,7 @@ bool hasDebuggableRoute(const T& routes) {
|
|||
void UserInputMapper::enableMapping(const Mapping::Pointer& mapping) {
|
||||
Locker locker(_lock);
|
||||
// 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
|
||||
// because standard -> action is the first set of routes added.
|
||||
Route::List standardRoutes = mapping->routes;
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
using namespace controller;
|
||||
|
||||
void ActionEndpoint::apply(float newValue, const Pointer& source) {
|
||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||
if(inputRecorder->isPlayingback()) {
|
||||
newValue = inputRecorder->getActionState(actionName);
|
||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||
QString actionName;
|
||||
if (inputRecorder->isPlayingback() || inputRecorder->isRecording()) {
|
||||
actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||
if (inputRecorder->isPlayingback()) {
|
||||
newValue = inputRecorder->getActionState(actionName);
|
||||
}
|
||||
}
|
||||
|
||||
_currentValue += newValue;
|
||||
|
@ -32,10 +35,12 @@ void ActionEndpoint::apply(float newValue, const Pointer& source) {
|
|||
|
||||
void ActionEndpoint::apply(const Pose& value, const Pointer& source) {
|
||||
_currentPose = value;
|
||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||
inputRecorder->setActionState(actionName, _currentPose);
|
||||
InputRecorder* inputRecorder = InputRecorder::getInstance();
|
||||
if (inputRecorder->isRecording()) {
|
||||
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
|
||||
inputRecorder->setActionState(actionName, _currentPose);
|
||||
}
|
||||
|
||||
if (!_currentPose.isValid()) {
|
||||
return;
|
||||
|
|
|
@ -530,7 +530,11 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur
|
|||
batch.setStateScissorRect(scissor);
|
||||
batch.setViewportTransform(viewport);
|
||||
batch.setResourceTexture(0, texture);
|
||||
#ifndef USE_GLES
|
||||
batch.setPipeline(_presentPipeline);
|
||||
#else
|
||||
batch.setPipeline(_simplePipeline);
|
||||
#endif
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
if (copyFbo) {
|
||||
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
|
||||
* 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>
|
||||
* @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>
|
||||
* @property {boolean} clientOnly=false - If <code>true</code> then the entity is an avatar entity; otherwise it is a server
|
||||
* 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
|
||||
* <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_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
|
||||
|
||||
// Rendering info
|
||||
|
|
|
@ -203,9 +203,9 @@ public slots:
|
|||
* Add a new entity with specified properties.
|
||||
* @function Entities.addEntity
|
||||
* @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
|
||||
* is created on the server. An avatar entity follows you to each domain you visit, rendering at the same world
|
||||
* coordinates unless it's parented to your avatar.
|
||||
* @param {boolean} [clientOnly=false] - If <code>true</code>, or if <code>clientOnly</code> is set <code>true</code> in
|
||||
* the properties, the entity is created as an avatar entity; otherwise it is created on the server. An avatar entity
|
||||
* 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}.
|
||||
* @example <caption>Create a box entity in front of your avatar.</caption>
|
||||
* var entityID = Entities.addEntity({
|
||||
|
|
|
@ -16,7 +16,8 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
|||
"system/+android/touchscreenvirtualpad.js",
|
||||
"system/+android/bottombar.js",
|
||||
"system/+android/audio.js" ,
|
||||
"system/+android/modes.js"/*,
|
||||
"system/+android/modes.js",
|
||||
"system/+android/stats.js"/*,
|
||||
"system/away.js",
|
||||
"system/controllers/controllerDisplayManager.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 "BakerCLI.h"
|
||||
#include "FBXBaker.h"
|
||||
#include "JSBaker.h"
|
||||
#include "TextureBaker.h"
|
||||
|
||||
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;
|
||||
|
||||
static const QString MODEL_EXTENSION { "fbx" };
|
||||
static const QString SCRIPT_EXTENSION { "js" };
|
||||
|
||||
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
|
||||
bool isFBX = extension == MODEL_EXTENSION;
|
||||
bool isScript = extension == SCRIPT_EXTENSION;
|
||||
|
||||
bool isSupportedImage = QImageReader::supportedImageFormats().contains(extension.toLatin1());
|
||||
|
||||
|
@ -57,12 +60,16 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString&
|
|||
outputPath)
|
||||
};
|
||||
_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) {
|
||||
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) };
|
||||
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||
} else {
|
||||
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
||||
QCoreApplication::exit(OVEN_STATUS_CODE_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
// invoke the bake method on the baker thread
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -31,6 +32,8 @@ class BakerCLI : public QObject {
|
|||
|
||||
public:
|
||||
BakerCLI(OvenCLIApplication* parent);
|
||||
|
||||
public slots:
|
||||
void bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type = QString::null);
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -40,7 +40,8 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
|||
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
||||
QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)));
|
||||
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 {
|
||||
parser.showHelp();
|
||||
QCoreApplication::quit();
|
||||
|
|
Loading…
Reference in a new issue