diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c27ac09d15..ce672be604 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1937,9 +1937,11 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + QPointer connectionPtr { connection }; + auto nodeList = DependencyManager::get(); - auto getSetting = [this](QString keyPath, QVariant value) -> bool { + auto getSetting = [this](QString keyPath, QVariant& value) -> bool { value = _settingsManager.valueForKeyPath(keyPath); if (!value.isValid()) { @@ -2120,30 +2122,38 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } else if (url.path() == URI_API_BACKUPS) { auto deferred = makePromise("getAllBackupsAndStatus"); - deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + if (!connectionPtr) { + return; + } + QJsonDocument docJSON(QJsonObject::fromVariantMap(result)); - connection->respond(HTTPConnection::StatusCode200, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); + connectionPtr->respond(HTTPConnection::StatusCode200, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); }); _contentManager->getAllBackupsAndStatus(deferred); return true; } else if (url.path().startsWith(URI_API_BACKUPS_ID)) { auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length()); auto deferred = makePromise("consolidateBackup"); - deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + if (!connectionPtr) { + return; + } + QJsonObject rootJSON; auto success = result["success"].toBool(); if (success) { auto path = result["backupFilePath"].toString(); auto file { std::unique_ptr(new QFile(path)) }; if (file->open(QIODevice::ReadOnly)) { - connection->respond(HTTPConnection::StatusCode200, std::move(file)); + connectionPtr->respond(HTTPConnection::StatusCode200, std::move(file)); } else { qCritical(domain_server) << "Unable to load consolidated backup at:" << path << result; - connection->respond(HTTPConnection::StatusCode500, "Error opening backup"); + connectionPtr->respond(HTTPConnection::StatusCode500, "Error opening backup"); } } else { - connection->respond(HTTPConnection::StatusCode400); + connectionPtr->respond(HTTPConnection::StatusCode400); } }); _contentManager->consolidateBackup(deferred, id); @@ -2264,12 +2274,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } else if (uploadedFilename.endsWith(".zip", Qt::CaseInsensitive)) { auto deferred = makePromise("recoverFromUploadedBackup"); - deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + if (!connectionPtr) { + return; + } + QJsonObject rootJSON; auto success = result["success"].toBool(); rootJSON["success"] = success; QJsonDocument docJSON(rootJSON); - connection->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), + connectionPtr->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); }); @@ -2297,12 +2311,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } auto deferred = makePromise("createManualBackup"); - deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + if (!connectionPtr) { + return; + } + QJsonObject rootJSON; auto success = result["success"].toBool(); rootJSON["success"] = success; QJsonDocument docJSON(rootJSON); - connection->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), + connectionPtr->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); }); _contentManager->createManualBackup(deferred, it.value()); @@ -2322,12 +2340,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } else if (url.path().startsWith(URI_API_BACKUPS_RECOVER)) { auto id = url.path().mid(QString(URI_API_BACKUPS_RECOVER).length()); auto deferred = makePromise("recoverFromBackup"); - deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + if (!connectionPtr) { + return; + } + QJsonObject rootJSON; auto success = result["success"].toBool(); rootJSON["success"] = success; QJsonDocument docJSON(rootJSON); - connection->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), + connectionPtr->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); }); _contentManager->recoverFromBackup(deferred, id); @@ -2423,12 +2445,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url if (url.path().startsWith(URI_API_BACKUPS_ID)) { auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length()); auto deferred = makePromise("deleteBackup"); - deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + if (!connectionPtr) { + return; + } + QJsonObject rootJSON; auto success = result["success"].toBool(); rootJSON["success"] = success; QJsonDocument docJSON(rootJSON); - connection->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), + connectionPtr->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); }); _contentManager->deleteBackup(deferred, id); diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index a12bd4b2c0..4626d9bcda 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -257,11 +257,7 @@ Item { id: octreeCol spacing: 4; x: 4; y: 4; StatText { - text: "Render Engine: " + root.engineFrameTime.toFixed(1) + " ms" - } - StatText { - visible: root.expanded - text: root.renderEngineStats + text: "Engine: " + root.engineFrameTime.toFixed(1) + " ms" } StatText { text: "Batch: " + root.batchFrameTime.toFixed(1) + " ms" diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index eab1e40af0..156332579a 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -112,6 +112,7 @@ Rectangle { // mute is in its own row RowLayout { + spacing: (margins.sizeCheckBox - 10.5) * 3; AudioControls.CheckBox { id: muteMic text: qsTr("Mute microphone"); @@ -123,6 +124,19 @@ Rectangle { checked = Qt.binding(function() { return AudioScriptingInterface.muted; }); // restore binding } } + + AudioControls.CheckBox { + id: stereoMic + spacing: muteMic.spacing; + text: qsTr("use stereo for stereo devices"); + checked: false; + onClicked: { + var success = Audio.setIsStereoInput(checked); + if (!success) { + checked = !checked; + } + } + } } RowLayout { @@ -204,6 +218,8 @@ Rectangle { text: devicename onPressed: { if (!checked) { + stereoMic.checked = false; + Audio.setIsStereoInput(false); // the next selected audio device might not support stereo AudioScriptingInterface.setInputDevice(info, bar.currentIndex === 1); } } diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index f1692acb3d..1fa9054d69 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -69,6 +69,10 @@ Item { hoverEnabled: true; } + Component.onDestruction: { + sendSignalToParent({method: 'maybeEnableHmdPreview'}); + } + // This will cause a bug -- if you bring up passphrase selection in HUD mode while // in HMD while having HMD preview enabled, then move, then finish passphrase selection, // HMD preview will stay off. diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml index 952390a7a4..fa065bc4de 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml @@ -236,6 +236,8 @@ Rectangle { } else { sendToScript(msg); } + } else if (msg.method === 'maybeEnableHmdPreview') { + sendToScript(msg); } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fa5206e128..d48d059bed 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -346,7 +346,7 @@ public: * restoreRoleAnimation() is used to restore a specified animation role's default animation clip. If you have not specified an override animation * for the specified role, this function will have no effect. * @function MyAvatar.restoreRoleAnimation - * @param rule {string} The animation role clip to restore + * @param role {string} The animation role clip to restore */ Q_INVOKABLE void restoreRoleAnimation(const QString& role); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ff42ed09e7..80f57bfe0e 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -482,7 +482,7 @@ void Stats::updateStats(bool force) { float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; _gameUpdateStats = QString("/idle/update = %1 ms").arg(dt); - QVector categories = { "devices", "physics", "otherAvatars", "MyAvatar", "pickManager", "postUpdateLambdas", "misc" }; + QVector categories = { "devices", "physics", "otherAvatars", "MyAvatar", "misc" }; for (int32_t j = 0; j < categories.size(); ++j) { QString recordKey = "/idle/update/" + categories[j]; itr = allRecords.find(recordKey); @@ -502,39 +502,10 @@ void Stats::updateStats(bool force) { _gameUpdateStats = ""; emit gameUpdateStatsChanged(); } - - itr = allRecords.find("/paintGL/display/EngineRun/Engine"); - std::priority_queue renderEngineStats; - if (itr != allRecords.end()) { - float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; - _renderEngineStats = QString("/render = %1 ms").arg(dt); - - QVector categories = { "RenderMainView", "SecondaryCameraJob", "UpdateScene"}; - for (int32_t j = 0; j < categories.size(); ++j) { - QString recordKey = "/paintGL/display/EngineRun/Engine/" + categories[j]; - itr = allRecords.find(recordKey); - if (itr != allRecords.end()) { - float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; - QString message = QString("\n %1 = %2").arg(categories[j]).arg(dt); - renderEngineStats.push(SortableStat(message, dt)); - } - } - while (!renderEngineStats.empty()) { - SortableStat stat = renderEngineStats.top(); - _renderEngineStats += stat.message; - renderEngineStats.pop(); - } - emit renderEngineStatsChanged(); - } else if (_renderEngineStats != "") { - _renderEngineStats = ""; - emit renderEngineStatsChanged(); - } } else if (_showGameUpdateStats) { _showGameUpdateStats = false; _gameUpdateStats = ""; - _renderEngineStats = ""; emit gameUpdateStatsChanged(); - emit renderEngineStatsChanged(); } } diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index e5fc0beaf6..af3189f20b 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -106,7 +106,6 @@ class Stats : public QQuickItem { STATS_PROPERTY(QString, lodStatus, QString()) STATS_PROPERTY(QString, timingStats, QString()) STATS_PROPERTY(QString, gameUpdateStats, QString()) - STATS_PROPERTY(QString, renderEngineStats, QString()) STATS_PROPERTY(int, serverElements, 0) STATS_PROPERTY(int, serverInternal, 0) STATS_PROPERTY(int, serverLeaves, 0) @@ -240,7 +239,6 @@ signals: void localLeavesChanged(); void timingStatsChanged(); void gameUpdateStatsChanged(); - void renderEngineStatsChanged(); void glContextSwapchainMemoryChanged(); void qmlTextureMemoryChanged(); void texturePendingTransfersChanged(); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 6603a44d46..651213ae99 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -681,5 +681,9 @@ scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() { } auto result = _model->getScriptableModel(); result.objectID = getID(); + { + std::lock_guard lock(_materialsLock); + result.appendMaterials(_materials); + } return result; } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 873d294303..e2dae92a94 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1397,9 +1397,11 @@ void AudioClient::setNoiseReduction(bool enable) { } -void AudioClient::setIsStereoInput(bool isStereoInput) { - if (isStereoInput != _isStereoInput) { +bool AudioClient::setIsStereoInput(bool isStereoInput) { + bool stereoInputChanged = false; + if (isStereoInput != _isStereoInput && _inputDeviceInfo.supportedChannelCounts().contains(2)) { _isStereoInput = isStereoInput; + stereoInputChanged = true; if (_isStereoInput) { _desiredInputFormat.setChannelCount(2); @@ -1419,6 +1421,8 @@ void AudioClient::setIsStereoInput(bool isStereoInput) { // restart the input device switchInputToAudioDevice(_inputDeviceInfo); } + + return stereoInputChanged; } bool AudioClient::outputLocalInjector(const AudioInjectorPointer& injector) { diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 3e6e83b598..053202f583 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -192,7 +192,7 @@ public slots: void toggleMute(); bool isMuted() { return _muted; } - virtual void setIsStereoInput(bool stereo) override; + virtual bool setIsStereoInput(bool stereo) override; void setNoiseReduction(bool isNoiseGateEnabled); bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; } diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h index 37731c31f7..ba1e733f13 100644 --- a/libraries/audio/src/AbstractAudioInterface.h +++ b/libraries/audio/src/AbstractAudioInterface.h @@ -41,7 +41,7 @@ public: public slots: virtual bool shouldLoopbackInjectors() { return false; } - virtual void setIsStereoInput(bool stereo) = 0; + virtual bool setIsStereoInput(bool stereo) = 0; }; Q_DECLARE_METATYPE(AbstractAudioInterface*) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f493bb14dd..65145d4c88 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1801,5 +1801,9 @@ scriptable::ScriptableModelBase Avatar::getScriptableModel() { } auto result = _skeletonModel->getScriptableModel(); result.objectID = getSessionUUID().isNull() ? AVATAR_SELF_ID : getSessionUUID(); + { + std::lock_guard lock(_materialsLock); + result.appendMaterials(_materials); + } return result; } \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5f926d1bb9..c484b99c23 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -974,6 +974,10 @@ scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScript auto result = _model->getScriptableModel(); result.objectID = getEntity()->getID(); + { + std::lock_guard lock(_materialsLock); + result.appendMaterials(_materials); + } return result; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 22cd98b08a..e5cbfdb59d 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -169,8 +169,12 @@ scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel() { auto geometryCache = DependencyManager::get(); auto geometryShape = geometryCache->getShapeForEntityShape(_shape); glm::vec3 vertexColor; - if (_materials["0"].top().material) { - vertexColor = _materials["0"].top().material->getAlbedo(); + { + std::lock_guard lock(_materialsLock); + result.appendMaterials(_materials); + if (_materials["0"].top().material) { + vertexColor = _materials["0"].top().material->getAlbedo(); + } } if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) { result.objectID = getEntity()->getID(); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 4a588c3c84..ed9505766b 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -868,16 +868,6 @@ void SphericalHarmonics::evalFromTexture(const Texture& texture) { // TextureSource -TextureSource::TextureSource() { -} - -TextureSource::~TextureSource() { -} - -void TextureSource::reset(const QUrl& url) { - _imageUrl = url; -} - void TextureSource::resetTexture(gpu::TexturePointer texture) { _gpuTexture = texture; } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index ad3dc5fada..a03b894e0d 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -647,13 +647,11 @@ typedef std::vector TextureViews; // It provides the mechanism to create a texture using a customizable TextureLoader class TextureSource { public: - TextureSource(); - ~TextureSource(); + TextureSource(const QUrl& url, int type = 0) : _imageUrl(url), _type(type) {} const QUrl& getUrl() const { return _imageUrl; } const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; } - - void reset(const QUrl& url); + int getType() const { return _type; } void resetTexture(gpu::TexturePointer texture); @@ -662,6 +660,7 @@ public: protected: gpu::TexturePointer _gpuTexture; QUrl _imageUrl; + int _type { 0 }; }; typedef std::shared_ptr< TextureSource > TextureSourcePointer; diff --git a/libraries/graphics-scripting/CMakeLists.txt b/libraries/graphics-scripting/CMakeLists.txt index ad8055b647..0f59fb41f8 100644 --- a/libraries/graphics-scripting/CMakeLists.txt +++ b/libraries/graphics-scripting/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME graphics-scripting) setup_hifi_library() -link_hifi_libraries(shared networking graphics fbx model-networking script-engine) +link_hifi_libraries(shared networking graphics fbx image model-networking script-engine) include_hifi_library_headers(gpu) diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index a0e186dda5..ed8e96a12f 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -6,9 +6,14 @@ #include #include #include +#include #include #include + +#include "graphics/Material.h" +#include "graphics/TextureMap.h" + namespace graphics { class Mesh; } @@ -31,6 +36,53 @@ namespace scriptable { using ModelProviderPointer = std::shared_ptr; using WeakModelProviderPointer = std::weak_ptr; + class ScriptableMaterial { + public: + ScriptableMaterial() {} + ScriptableMaterial(const graphics::MaterialPointer& material); + ScriptableMaterial(const ScriptableMaterial& material) { *this = material; } + ScriptableMaterial& operator=(const ScriptableMaterial& material); + + QString name; + QString model; + float opacity; + float roughness; + float metallic; + float scattering; + bool unlit; + glm::vec3 emissive; + glm::vec3 albedo; + QString emissiveMap; + QString albedoMap; + QString opacityMap; + QString metallicMap; + QString specularMap; + QString roughnessMap; + QString glossMap; + QString normalMap; + QString bumpMap; + QString occlusionMap; + QString lightmapMap; + QString scatteringMap; + }; + + /**jsdoc + * @typedef {object} Graphics.MaterialLayer + * @property {Material} material - This layer's material. + * @property {number} priority - The priority of this layer. If multiple materials are applied to a mesh part, only the highest priority layer is used. + */ + class ScriptableMaterialLayer { + public: + ScriptableMaterialLayer() {} + ScriptableMaterialLayer(const graphics::MaterialLayer& materialLayer) : material(materialLayer.material), priority(materialLayer.priority) {} + ScriptableMaterialLayer(const ScriptableMaterialLayer& materialLayer) { *this = materialLayer; } + ScriptableMaterialLayer& operator=(const ScriptableMaterialLayer& materialLayer); + + ScriptableMaterial material; + quint16 priority; + }; + typedef QHash> MultiMaterialMap; + class ScriptableMeshBase : public QObject { Q_OBJECT public: @@ -55,6 +107,8 @@ namespace scriptable { WeakModelProviderPointer provider; QUuid objectID; // spatially nestable ID QVector meshes; + MultiMaterialMap materialLayers; + QVector materialNames; ScriptableModelBase(QObject* parent = nullptr) : QObject(parent) {} ScriptableModelBase(const ScriptableModelBase& other) : QObject(other.parent()) { *this = other; } @@ -63,9 +117,11 @@ namespace scriptable { void append(const ScriptableMeshBase& mesh); void append(scriptable::WeakMeshPointer mesh); + void appendMaterial(const graphics::MaterialLayer& materialLayer, int shapeID, std::string materialName); + void appendMaterials(const std::unordered_map& materialsToAppend); + void appendMaterialNames(const std::vector& names); // TODO: in future containers for these could go here // QVariantMap shapes; - // QVariantMap materials; // QVariantMap armature; }; diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index f3ba5e8406..20b54b02c9 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -297,6 +297,10 @@ namespace { qRegisterMetaType(), qRegisterMetaType(), qRegisterMetaType(), + qRegisterMetaType(), + qRegisterMetaType(), + qRegisterMetaType>(), + qRegisterMetaType(), qRegisterMetaType(), }; } @@ -335,6 +339,67 @@ namespace scriptable { ); } + QScriptValue qVectorScriptableMaterialLayerToScriptValue(QScriptEngine* engine, const QVector& vector) { + return qScriptValueFromSequence(engine, vector); + } + + void qVectorScriptableMaterialLayerFromScriptValue(const QScriptValue& array, QVector& result) { + qScriptValueToSequence(array, result); + } + + QScriptValue scriptableMaterialToScriptValue(QScriptEngine* engine, const scriptable::ScriptableMaterial &material) { + QScriptValue obj = engine->newObject(); + obj.setProperty("name", material.name); + obj.setProperty("model", material.model); + obj.setProperty("opacity", material.opacity); + obj.setProperty("roughness", material.roughness); + obj.setProperty("metallic", material.metallic); + obj.setProperty("scattering", material.scattering); + obj.setProperty("unlit", material.unlit); + obj.setProperty("emissive", vec3toScriptValue(engine, material.emissive)); + obj.setProperty("albedo", vec3toScriptValue(engine, material.albedo)); + obj.setProperty("emissiveMap", material.emissiveMap); + obj.setProperty("albedoMap", material.albedoMap); + obj.setProperty("opacityMap", material.opacityMap); + obj.setProperty("metallicMap", material.metallicMap); + obj.setProperty("specularMap", material.specularMap); + obj.setProperty("roughnessMap", material.roughnessMap); + obj.setProperty("glossMap", material.glossMap); + obj.setProperty("normalMap", material.normalMap); + obj.setProperty("bumpMap", material.bumpMap); + obj.setProperty("occlusionMap", material.occlusionMap); + obj.setProperty("lightmapMap", material.lightmapMap); + obj.setProperty("scatteringMap", material.scatteringMap); + return obj; + } + + void scriptableMaterialFromScriptValue(const QScriptValue &object, scriptable::ScriptableMaterial& material) { + // No need to convert from QScriptValue to ScriptableMaterial + } + + QScriptValue scriptableMaterialLayerToScriptValue(QScriptEngine* engine, const scriptable::ScriptableMaterialLayer &materialLayer) { + QScriptValue obj = engine->newObject(); + obj.setProperty("material", scriptableMaterialToScriptValue(engine, materialLayer.material)); + obj.setProperty("priority", materialLayer.priority); + return obj; + } + + void scriptableMaterialLayerFromScriptValue(const QScriptValue &object, scriptable::ScriptableMaterialLayer& materialLayer) { + // No need to convert from QScriptValue to ScriptableMaterialLayer + } + + QScriptValue multiMaterialMapToScriptValue(QScriptEngine* engine, const scriptable::MultiMaterialMap& map) { + QScriptValue obj = engine->newObject(); + for (auto key : map.keys()) { + obj.setProperty(key, qVectorScriptableMaterialLayerToScriptValue(engine, map[key])); + } + return obj; + } + + void multiMaterialMapFromScriptValue(const QScriptValue& map, scriptable::MultiMaterialMap& result) { + // No need to convert from QScriptValue to MultiMaterialMap + } + template int registerDebugEnum(QScriptEngine* engine, const DebugEnums& debugEnums) { static const DebugEnums& instance = debugEnums; return qScriptRegisterMetaType( @@ -351,6 +416,7 @@ namespace scriptable { void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) { qScriptRegisterSequenceMetaType>(engine); + qScriptRegisterSequenceMetaType>(engine); scriptable::registerQPointerMetaType(engine); scriptable::registerQPointerMetaType(engine); @@ -361,6 +427,11 @@ void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) { scriptable::registerDebugEnum(engine, gpu::SEMANTICS); scriptable::registerDebugEnum(engine, gpu::DIMENSIONS); + qScriptRegisterMetaType(engine, scriptable::scriptableMaterialToScriptValue, scriptable::scriptableMaterialFromScriptValue); + qScriptRegisterMetaType(engine, scriptable::scriptableMaterialLayerToScriptValue, scriptable::scriptableMaterialLayerFromScriptValue); + qScriptRegisterMetaType(engine, scriptable::qVectorScriptableMaterialLayerToScriptValue, scriptable::qVectorScriptableMaterialLayerFromScriptValue); + qScriptRegisterMetaType(engine, scriptable::multiMaterialMapToScriptValue, scriptable::multiMaterialMapFromScriptValue); + Q_UNUSED(metaTypeIds); } diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp index bc31d45229..8e6d4bec9b 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp @@ -400,6 +400,5 @@ scriptable::ScriptableMesh::~ScriptableMesh() { strongMesh.reset(); } - #include "ScriptableMesh.moc" diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index 36322d170d..c65764a225 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -14,14 +14,120 @@ #include +#include "graphics/Material.h" + +#include "image/Image.h" + // #define SCRIPTABLE_MESH_DEBUG 1 +scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const scriptable::ScriptableMaterial& material) { + name = material.name; + model = material.model; + opacity = material.opacity; + roughness = material.roughness; + metallic = material.metallic; + scattering = material.scattering; + unlit = material.unlit; + emissive = material.emissive; + albedo = material.albedo; + emissiveMap = material.emissiveMap; + albedoMap = material.albedoMap; + opacityMap = material.opacityMap; + metallicMap = material.metallicMap; + specularMap = material.specularMap; + roughnessMap = material.roughnessMap; + glossMap = material.glossMap; + normalMap = material.normalMap; + bumpMap = material.bumpMap; + occlusionMap = material.occlusionMap; + lightmapMap = material.lightmapMap; + scatteringMap = material.scatteringMap; + + return *this; +} + +scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPointer& material) : + name(material->getName().c_str()), + model(material->getModel().c_str()), + opacity(material->getOpacity()), + roughness(material->getRoughness()), + metallic(material->getMetallic()), + scattering(material->getScattering()), + unlit(material->isUnlit()), + emissive(material->getEmissive()), + albedo(material->getAlbedo()) +{ + auto map = material->getTextureMap(graphics::Material::MapChannel::EMISSIVE_MAP); + if (map && map->getTextureSource()) { + emissiveMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::ALBEDO_MAP); + if (map && map->getTextureSource()) { + albedoMap = map->getTextureSource()->getUrl().toString(); + if (map->useAlphaChannel()) { + opacityMap = albedoMap; + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::METALLIC_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::METALLIC_TEXTURE) { + metallicMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::SPECULAR_TEXTURE) { + specularMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::ROUGHNESS_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::ROUGHNESS_TEXTURE) { + roughnessMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::GLOSS_TEXTURE) { + glossMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::NORMAL_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::NORMAL_TEXTURE) { + normalMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::BUMP_TEXTURE) { + bumpMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::OCCLUSION_MAP); + if (map && map->getTextureSource()) { + occlusionMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::LIGHTMAP_MAP); + if (map && map->getTextureSource()) { + lightmapMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::SCATTERING_MAP); + if (map && map->getTextureSource()) { + scatteringMap = map->getTextureSource()->getUrl().toString(); + } +} + +scriptable::ScriptableMaterialLayer& scriptable::ScriptableMaterialLayer::operator=(const scriptable::ScriptableMaterialLayer& materialLayer) { + material = materialLayer.material; + priority = materialLayer.priority; + + return *this; +} + scriptable::ScriptableModelBase& scriptable::ScriptableModelBase::operator=(const scriptable::ScriptableModelBase& other) { provider = other.provider; objectID = other.objectID; for (const auto& mesh : other.meshes) { append(mesh); } + materialLayers = other.materialLayers; + materialNames = other.materialNames; return *this; } @@ -34,6 +140,8 @@ scriptable::ScriptableModelBase::~ScriptableModelBase() { m.strongMesh.reset(); } meshes.clear(); + materialLayers.clear(); + materialNames.clear(); } void scriptable::ScriptableModelBase::append(scriptable::WeakMeshPointer mesh) { @@ -47,6 +155,27 @@ void scriptable::ScriptableModelBase::append(const ScriptableMeshBase& mesh) { meshes << mesh; } +void scriptable::ScriptableModelBase::appendMaterial(const graphics::MaterialLayer& materialLayer, int shapeID, std::string materialName) { + materialLayers[QString::number(shapeID)].push_back(ScriptableMaterialLayer(materialLayer)); + materialLayers["mat::" + QString::fromStdString(materialName)].push_back(ScriptableMaterialLayer(materialLayer)); +} + +void scriptable::ScriptableModelBase::appendMaterials(const std::unordered_map& materialsToAppend) { + auto materialsToAppendCopy = materialsToAppend; + for (auto& multiMaterial : materialsToAppendCopy) { + while (!multiMaterial.second.empty()) { + materialLayers[QString(multiMaterial.first.c_str())].push_back(ScriptableMaterialLayer(multiMaterial.second.top())); + multiMaterial.second.pop(); + } + } +} + +void scriptable::ScriptableModelBase::appendMaterialNames(const std::vector& names) { + for (auto& name : names) { + materialNames.append(QString::fromStdString(name)); + } +} + QString scriptable::ScriptableModel::toString() const { return QString("[ScriptableModel%1%2 numMeshes=%3]") .arg(objectID.isNull() ? "" : " objectID="+objectID.toString()) diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h index 9a4c4f695b..ac0b7b9623 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h @@ -21,6 +21,8 @@ namespace scriptable { * @property {Uuid} objectID - UUID of corresponding inworld object (if model is associated) * @property {number} numMeshes - The number of submeshes contained in the model. * @property {Graphics.Mesh[]} meshes - Array of submesh references. + * @property {Object.} materialLayers - Map of materials layer lists. You can look up a material layer list by mesh part number or by material name. + * @property {string[]} materialNames - Array of all the material names used by the mesh parts of this model, in order (e.g. materialNames[0] is the name of the first mesh part's material). */ class ScriptableModel : public ScriptableModelBase { @@ -28,18 +30,24 @@ namespace scriptable { Q_PROPERTY(QUuid objectID MEMBER objectID CONSTANT) Q_PROPERTY(glm::uint32 numMeshes READ getNumMeshes) Q_PROPERTY(ScriptableMeshes meshes READ getMeshes) + Q_PROPERTY(scriptable::MultiMaterialMap materialLayers READ getMaterialLayers) + Q_PROPERTY(QVector materialNames READ getMaterialNames) public: ScriptableModel(QObject* parent = nullptr) : ScriptableModelBase(parent) {} ScriptableModel(const ScriptableModel& other) : ScriptableModelBase(other) {} ScriptableModel(const ScriptableModelBase& other) : ScriptableModelBase(other) {} ScriptableModel& operator=(const ScriptableModelBase& view) { ScriptableModelBase::operator=(view); return *this; } + operator scriptable::ScriptableModelBasePointer() { return QPointer(qobject_cast(this)); } ScriptableMeshes getMeshes(); const ScriptableMeshes getConstMeshes() const; + scriptable::MultiMaterialMap getMaterialLayers() { return materialLayers; } + QVector getMaterialNames() { return materialNames; } + public slots: scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap()); QString toString() const; @@ -53,3 +61,6 @@ namespace scriptable { Q_DECLARE_METATYPE(scriptable::ScriptableModelPointer) Q_DECLARE_METATYPE(QVector) +Q_DECLARE_METATYPE(scriptable::ScriptableMaterial) +Q_DECLARE_METATYPE(scriptable::ScriptableMaterialLayer) +Q_DECLARE_METATYPE(scriptable::MultiMaterialMap) diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 632cf99391..f9e83a0324 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -356,8 +356,9 @@ public: void setTextureTransforms(const Transform& transform); - const std::string& getName() { return _name; } + const std::string& getName() const { return _name; } + const std::string& getModel() const { return _model; } void setModel(const std::string& model) { _model = model; } protected: diff --git a/libraries/model-networking/src/model-networking/MaterialCache.cpp b/libraries/model-networking/src/model-networking/MaterialCache.cpp index 8d9d6571f8..85f2f43652 100644 --- a/libraries/model-networking/src/model-networking/MaterialCache.cpp +++ b/libraries/model-networking/src/model-networking/MaterialCache.cpp @@ -11,6 +11,8 @@ #include "QJsonDocument" #include "QJsonArray" +#include "RegisteredMetaTypes.h" + NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) : Resource(url) {} @@ -39,6 +41,11 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3& color = glm::vec3(colorArray[0].toDouble(), colorArray[1].toDouble(), colorArray[2].toDouble()); return true; } + } else if (array.isObject()) { + bool toReturn; + isSRGB = true; + color = vec3FromVariant(array.toObject(), toReturn); + return toReturn; } return false; } diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 912a44cb97..ffc9af5264 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -294,7 +294,7 @@ _type(), _sourceIsKTX(false), _maxNumPixels(100) { - _textureSource = std::make_shared(); + _textureSource = std::make_shared(url); _lowestRequestedMipLevel = 0; _loaded = true; } @@ -310,7 +310,7 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, _sourceIsKTX(url.path().endsWith(".ktx")), _maxNumPixels(maxNumPixels) { - _textureSource = std::make_shared(); + _textureSource = std::make_shared(url, (int)type); _lowestRequestedMipLevel = 0; _shouldFailOnRedirect = !_sourceIsKTX; diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 77ed589e0b..b34c05106f 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -578,6 +578,7 @@ void Connection::processControl(ControlPacketPointer controlPacket) { #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Got handshake request, stopping SendQueue"; #endif + _hasReceivedHandshakeACK = false; stopSendQueue(); } break; diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 334299185e..7e0c82506b 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1778,7 +1778,7 @@ bool Octree::writeToFile(const char* fileName, const OctreeElementPointer& eleme return success; } -bool Octree::toJSON(QJsonDocument* doc, const OctreeElementPointer& element) { +bool Octree::toJSONDocument(QJsonDocument* doc, const OctreeElementPointer& element) { QVariantMap entityDescription; OctreeElementPointer top; @@ -1804,18 +1804,22 @@ bool Octree::toJSON(QJsonDocument* doc, const OctreeElementPointer& element) { return true; } -bool Octree::toGzippedJSON(QByteArray* data, const OctreeElementPointer& element) { +bool Octree::toJSON(QByteArray* data, const OctreeElementPointer& element, bool doGzip) { QJsonDocument doc; - if (!toJSON(&doc, element)) { + if (!toJSONDocument(&doc, element)) { qCritical("Failed to convert Entities to QVariantMap while converting to json."); return false; } - QByteArray jsonData = doc.toJson(); + if (doGzip) { + QByteArray jsonData = doc.toJson(); - if (!gzip(jsonData, *data, -1)) { - qCritical("Unable to gzip data while saving to json."); - return false; + if (!gzip(jsonData, *data, -1)) { + qCritical("Unable to gzip data while saving to json."); + return false; + } + } else { + *data = doc.toJson(); } return true; @@ -1825,7 +1829,7 @@ bool Octree::writeToJSONFile(const char* fileName, const OctreeElementPointer& e qCDebug(octree, "Saving JSON SVO to file %s...", fileName); QByteArray jsonDataForFile; - if (!toGzippedJSON(&jsonDataForFile)) { + if (!toJSON(&jsonDataForFile, element, doGzip)) { return false; } @@ -1837,7 +1841,6 @@ bool Octree::writeToJSONFile(const char* fileName, const OctreeElementPointer& e qCritical("Could not write to JSON description of entities."); } - return success; } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index cb281593b1..c4c4508138 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -284,8 +284,8 @@ public: void loadOctreeFile(const char* fileName); // Octree exporters - bool toJSON(QJsonDocument* doc, const OctreeElementPointer& element = nullptr); - bool toGzippedJSON(QByteArray* data, const OctreeElementPointer& element = nullptr); + bool toJSONDocument(QJsonDocument* doc, const OctreeElementPointer& element = nullptr); + bool toJSON(QByteArray* data, const OctreeElementPointer& element = nullptr, bool doGzip = false); bool writeToFile(const char* filename, const OctreeElementPointer& element = nullptr, QString persistAsFileType = "json.gz"); bool writeToJSONFile(const char* filename, const OctreeElementPointer& element = nullptr, bool doGzip = false); virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues, diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 23d6b6c2aa..7c5b7eb45c 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -341,7 +341,7 @@ void OctreePersistThread::sendLatestEntityDataToDS() { const DomainHandler& domainHandler = nodeList->getDomainHandler(); QByteArray data; - if (_tree->toGzippedJSON(&data)) { + if (_tree->toJSON(&data, nullptr, true)) { auto message = NLPacketList::create(PacketType::OctreeDataPersist, QByteArray(), true, true); message->write(data); nodeList->sendPacketList(std::move(message), domainHandler.getSockAddr()); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 6806b41647..226ac0e777 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -62,6 +62,7 @@ void CauterizedModel::createVisibleRenderItemSet() { Q_ASSERT(_modelMeshRenderItems.isEmpty()); _modelMeshRenderItems.clear(); + _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); Transform transform; @@ -86,6 +87,7 @@ void CauterizedModel::createVisibleRenderItemSet() { for (int partIndex = 0; partIndex < numParts; partIndex++) { auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); _modelMeshRenderItems << std::static_pointer_cast(ptr); + _modelMeshMaterialNames.push_back(getGeometry()->getShapeMaterial(shapeID)->getName()); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); shapeID++; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 12d6659849..830289305d 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -684,12 +684,20 @@ scriptable::ScriptableModelBase Model::getScriptableModel() { const FBXGeometry& geometry = getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); + int shapeID = 0; for (int i = 0; i < numberOfMeshes; i++) { const FBXMesh& fbxMesh = geometry.meshes.at(i); if (auto mesh = fbxMesh._mesh) { result.append(mesh); + + int numParts = (int)mesh->getNumParts(); + for (int partIndex = 0; partIndex < numParts; partIndex++) { + result.appendMaterial(graphics::MaterialLayer(getGeometry()->getShapeMaterial(shapeID), 0), shapeID, _modelMeshMaterialNames[shapeID]); + shapeID++; + } } } + result.appendMaterialNames(_modelMeshMaterialNames); return result; } diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index 28bf5ed163..dd8d284c12 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -60,8 +60,10 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(SharedSoundPointer sound } } -void AudioScriptingInterface::setStereoInput(bool stereo) { +bool AudioScriptingInterface::setStereoInput(bool stereo) { + bool stereoInputChanged = false; if (_localAudioInterface) { - _localAudioInterface->setIsStereoInput(stereo); + stereoInputChanged = _localAudioInterface->setIsStereoInput(stereo); } + return stereoInputChanged; } diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index 23a0861acd..d46430ccce 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -35,7 +35,7 @@ protected: // FIXME: there is no way to play a positionless sound Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound, const QVector3D& position); - Q_INVOKABLE void setStereoInput(bool stereo); + Q_INVOKABLE bool setStereoInput(bool stereo); signals: void mutedByMixer(); /// the client has been muted by the mixer diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 18b194dd3a..4f041d3067 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -43,6 +43,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.totalVariance = 0; this.highVarianceCount = 0; this.veryhighVarianceCount = 0; + this.orderedPluginNames = []; this.tabletID = null; this.blacklist = []; this.pointerManager = new PointerManager(); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 2b29fbf041..02bf233279 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -321,22 +321,19 @@ function multiDataUpdater(groupName, updateKeyPair, userDataElement, defaults) { } var keys = Object.keys(updateKeyPair); keys.forEach(function (key) { - delete parsedData[groupName][key]; if (updateKeyPair[key] !== null && updateKeyPair[key] !== "null") { if (updateKeyPair[key] instanceof Element) { if (updateKeyPair[key].type === "checkbox") { - if (updateKeyPair[key].checked !== defaults[key]) { - parsedData[groupName][key] = updateKeyPair[key].checked; - } + parsedData[groupName][key] = updateKeyPair[key].checked; } else { var val = isNaN(updateKeyPair[key].value) ? updateKeyPair[key].value : parseInt(updateKeyPair[key].value); - if (val !== defaults[key]) { - parsedData[groupName][key] = val; - } + parsedData[groupName][key] = val; } } else { parsedData[groupName][key] = updateKeyPair[key]; } + } else if (defaults[key] !== null && defaults[key] !== "null") { + parsedData[groupName][key] = defaults[key]; } }); if (Object.keys(parsedData[groupName]).length === 0) { @@ -1281,7 +1278,7 @@ function loaded() { if (elCloneable.checked) { elGrabbable.checked = false; } - userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); + userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, true); }); elCloneableDynamic.addEventListener('change', function(event) { userDataChanger("grabbableKey", "cloneDynamic", event.target, elUserData, -1); diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 8f51d88f2d..b3ca300022 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -115,13 +115,15 @@ var selectionDisplay = null; // for gridTool.js to ignore var filterText; // Used for updating Purchases QML var onWalletScreen = false; + var onCommerceScreen = false; + function onScreenChanged(type, url) { onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1; var onWalletScreenNow = url.indexOf(MARKETPLACE_WALLET_QML_PATH) !== -1; - onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH + var onCommerceScreenNow = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1); - if (!onWalletScreenNow && onWalletScreen) { // exiting wallet screen + if ((!onWalletScreenNow && onWalletScreen) || (!onCommerceScreenNow && onCommerceScreen)) { // exiting wallet or commerce screen if (isHmdPreviewDisabledBySecurity) { DesktopPreviewProvider.setPreviewDisabledReason("USER"); Menu.setIsOptionChecked("Disable Preview", false); @@ -129,6 +131,7 @@ var selectionDisplay = null; // for gridTool.js to ignore } } + onCommerceScreen = onCommerceScreenNow; onWalletScreen = onWalletScreenNow; wireEventBridge(onMarketplaceScreen || onCommerceScreen || onWalletScreen); diff --git a/tools/oven/src/BakerCLI.cpp b/tools/oven/src/BakerCLI.cpp index 5af65c4dc0..f5af5455fb 100644 --- a/tools/oven/src/BakerCLI.cpp +++ b/tools/oven/src/BakerCLI.cpp @@ -14,13 +14,14 @@ #include #include +#include "OvenCLIApplication.h" #include "ModelBakingLoggingCategory.h" -#include "Oven.h" #include "BakerCLI.h" #include "FBXBaker.h" #include "TextureBaker.h" -BakerCLI::BakerCLI(Oven* parent) : QObject(parent) { +BakerCLI::BakerCLI(OvenCLIApplication* parent) : QObject(parent) { + } void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type) { @@ -50,14 +51,18 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString& // create our appropiate baker if (isFBX) { - _baker = std::unique_ptr { new FBXBaker(inputUrl, []() -> QThread* { return qApp->getNextWorkerThread(); }, outputPath) }; - _baker->moveToThread(qApp->getNextWorkerThread()); + _baker = std::unique_ptr { + new FBXBaker(inputUrl, + []() -> QThread* { return Oven::instance().getNextWorkerThread(); }, + outputPath) + }; + _baker->moveToThread(Oven::instance().getNextWorkerThread()); } else if (isSupportedImage) { _baker = std::unique_ptr { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) }; - _baker->moveToThread(qApp->getNextWorkerThread()); + _baker->moveToThread(Oven::instance().getNextWorkerThread()); } else { qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl; - QApplication::exit(OVEN_STATUS_CODE_FAIL); + QCoreApplication::exit(OVEN_STATUS_CODE_FAIL); } // invoke the bake method on the baker thread @@ -81,5 +86,5 @@ void BakerCLI::handleFinishedBaker() { errorFile.close(); } } - QApplication::exit(exitCode); + QCoreApplication::exit(exitCode); } diff --git a/tools/oven/src/BakerCLI.h b/tools/oven/src/BakerCLI.h index 7d362eb898..4f5b6607b0 100644 --- a/tools/oven/src/BakerCLI.h +++ b/tools/oven/src/BakerCLI.h @@ -18,7 +18,7 @@ #include #include "Baker.h" -#include "Oven.h" +#include "OvenCLIApplication.h" static const int OVEN_STATUS_CODE_SUCCESS { 0 }; static const int OVEN_STATUS_CODE_FAIL { 1 }; @@ -27,10 +27,10 @@ static const int OVEN_STATUS_CODE_ABORT { 2 }; static const QString OVEN_ERROR_FILENAME = "errors.txt"; class BakerCLI : public QObject { - Q_OBJECT + Q_OBJECT public: - BakerCLI(Oven* parent); + BakerCLI(OvenCLIApplication* parent); void bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type = QString::null); private slots: diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index edc2492e82..28ede982a0 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -201,7 +201,7 @@ void DomainBaker::enumerateEntities() { } QSharedPointer baker { new FBXBaker(modelURL, []() -> QThread* { - return qApp->getNextWorkerThread(); + return Oven::instance().getNextWorkerThread(); }, _contentOutputPath + subDirName + "/baked", _contentOutputPath + subDirName + "/original"), &FBXBaker::deleteLater }; @@ -214,7 +214,7 @@ void DomainBaker::enumerateEntities() { // move the baker to the baker thread // and kickoff the bake - baker->moveToThread(qApp->getNextWorkerThread()); + baker->moveToThread(Oven::instance().getNextWorkerThread()); QMetaObject::invokeMethod(baker.data(), "bake"); // keep track of the total number of baking entities @@ -285,7 +285,7 @@ void DomainBaker::bakeSkybox(QUrl skyboxURL, QJsonValueRef entity) { _skyboxBakers.insert(skyboxURL, skyboxBaker); // move the baker to a worker thread and kickoff the bake - skyboxBaker->moveToThread(qApp->getNextWorkerThread()); + skyboxBaker->moveToThread(Oven::instance().getNextWorkerThread()); QMetaObject::invokeMethod(skyboxBaker.data(), "bake"); // keep track of the total number of baking entities diff --git a/tools/oven/src/Oven.cpp b/tools/oven/src/Oven.cpp index 69d2ef84ce..650683e1f0 100644 --- a/tools/oven/src/Oven.cpp +++ b/tools/oven/src/Oven.cpp @@ -11,33 +11,15 @@ #include #include -#include #include -#include "ui/OvenMainWindow.h" #include "Oven.h" -#include "BakerCLI.h" -static const QString OUTPUT_FOLDER = "/Users/birarda/code/hifi/lod/test-oven/export"; +Oven* Oven::_staticInstance { nullptr }; -static const QString CLI_INPUT_PARAMETER = "i"; -static const QString CLI_OUTPUT_PARAMETER = "o"; -static const QString CLI_TYPE_PARAMETER = "t"; - -Oven::Oven(int argc, char* argv[]) : - QApplication(argc, argv) -{ - // parse the command line parameters - QCommandLineParser parser; - - parser.addOptions({ - { CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" }, - { CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" }, - { CLI_TYPE_PARAMETER, "Type of asset.", "type" } - }); - parser.addHelpOption(); - parser.process(*this); +Oven::Oven() { + _staticInstance = this; // enable compression in image library image::setColorTexturesCompressionEnabled(true); @@ -47,41 +29,30 @@ Oven::Oven(int argc, char* argv[]) : // setup our worker threads setupWorkerThreads(QThread::idealThreadCount()); - - // check if we were passed any command line arguments that would tell us just to run without the GUI - if (parser.isSet(CLI_INPUT_PARAMETER) || parser.isSet(CLI_OUTPUT_PARAMETER)) { - if (parser.isSet(CLI_INPUT_PARAMETER) && parser.isSet(CLI_OUTPUT_PARAMETER)) { - BakerCLI* cli = new BakerCLI(this); - 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); - } else { - parser.showHelp(); - QApplication::quit(); - } - } else { - // setup the GUI - _mainWindow = new OvenMainWindow; - _mainWindow->show(); - } } Oven::~Oven() { - // cleanup the worker threads - for (auto i = 0; i < _workerThreads.size(); ++i) { - _workerThreads[i]->quit(); - _workerThreads[i]->wait(); + // quit all worker threads and wait on them + for (auto& thread : _workerThreads) { + thread->quit(); } + + for (auto& thread: _workerThreads) { + thread->wait(); + } + + _staticInstance = nullptr; } void Oven::setupWorkerThreads(int numWorkerThreads) { + _workerThreads.reserve(numWorkerThreads); + for (auto i = 0; i < numWorkerThreads; ++i) { // setup a worker thread yet and add it to our concurrent vector - auto newThread = new QThread(this); + auto newThread = std::unique_ptr { new QThread }; newThread->setObjectName("Oven Worker Thread " + QString::number(i + 1)); - _workerThreads.push_back(newThread); + _workerThreads.push_back(std::move(newThread)); } } @@ -92,13 +63,13 @@ QThread* Oven::getNextWorkerThread() { // (for the FBX Baker Thread to have room), and cycle through them to hand a usable running thread back to our callers. auto nextIndex = ++_nextWorkerThreadIndex; - auto nextThread = _workerThreads[nextIndex % _workerThreads.size()]; + auto& nextThread = _workerThreads[nextIndex % _workerThreads.size()]; // start the thread if it isn't running yet if (!nextThread->isRunning()) { nextThread->start(); } - return nextThread; + return nextThread.get(); } diff --git a/tools/oven/src/Oven.h b/tools/oven/src/Oven.h index 928ba4eb11..effebb472e 100644 --- a/tools/oven/src/Oven.h +++ b/tools/oven/src/Oven.h @@ -12,27 +12,16 @@ #ifndef hifi_Oven_h #define hifi_Oven_h -#include - -#include - #include +#include -#if defined(qApp) -#undef qApp -#endif -#define qApp (static_cast(QCoreApplication::instance())) - -class OvenMainWindow; - -class Oven : public QApplication { - Q_OBJECT +class Oven { public: - Oven(int argc, char* argv[]); + Oven(); ~Oven(); - OvenMainWindow* getMainWindow() const { return _mainWindow; } + static Oven& instance() { return *_staticInstance; } QThread* getNextWorkerThread(); @@ -40,11 +29,12 @@ private: void setupWorkerThreads(int numWorkerThreads); void setupFBXBakerThread(); - OvenMainWindow* _mainWindow; - QList _workerThreads; + std::vector> _workerThreads; std::atomic _nextWorkerThreadIndex; int _numWorkerThreads; + + static Oven* _staticInstance; }; diff --git a/tools/oven/src/OvenCLIApplication.cpp b/tools/oven/src/OvenCLIApplication.cpp new file mode 100644 index 0000000000..38d9963eeb --- /dev/null +++ b/tools/oven/src/OvenCLIApplication.cpp @@ -0,0 +1,49 @@ +// +// OvenCLIApplication.cpp +// tools/oven/src +// +// Created by Stephen Birarda on 2/20/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 +// + +#include +#include + +#include "BakerCLI.h" + +#include "OvenCLIApplication.h" + +static const QString CLI_INPUT_PARAMETER = "i"; +static const QString CLI_OUTPUT_PARAMETER = "o"; +static const QString CLI_TYPE_PARAMETER = "t"; + +OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) : + QCoreApplication(argc, argv) +{ + // parse the command line parameters + QCommandLineParser parser; + + parser.addOptions({ + { CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" }, + { CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" }, + { CLI_TYPE_PARAMETER, "Type of asset.", "type" } + }); + + parser.addHelpOption(); + parser.process(*this); + + if (parser.isSet(CLI_INPUT_PARAMETER) && parser.isSet(CLI_OUTPUT_PARAMETER)) { + BakerCLI* cli = new BakerCLI(this); + 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); + } else { + parser.showHelp(); + QCoreApplication::quit(); + } + +} diff --git a/tools/oven/src/OvenCLIApplication.h b/tools/oven/src/OvenCLIApplication.h new file mode 100644 index 0000000000..5d81166f69 --- /dev/null +++ b/tools/oven/src/OvenCLIApplication.h @@ -0,0 +1,27 @@ +// +// OvenCLIApplication.h +// tools/oven/src +// +// Created by Stephen Birarda on 2/20/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 +// + +#ifndef hifi_OvenCLIApplication_h +#define hifi_OvenCLIApplication_h + +#include + +#include "Oven.h" + +class OvenCLIApplication : public QCoreApplication, public Oven { + Q_OBJECT +public: + OvenCLIApplication(int argc, char* argv[]); + + static OvenCLIApplication* instance() { return dynamic_cast(QCoreApplication::instance()); } +}; + +#endif // hifi_OvenCLIApplication_h diff --git a/tools/oven/src/OvenGUIApplication.cpp b/tools/oven/src/OvenGUIApplication.cpp new file mode 100644 index 0000000000..33dc375634 --- /dev/null +++ b/tools/oven/src/OvenGUIApplication.cpp @@ -0,0 +1,19 @@ +// +// OvenGUIApplication.cpp +// tools/src/oven +// +// Created by Stephen Birarda on 2/20/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 +// + +#include "OvenGUIApplication.h" + +OvenGUIApplication::OvenGUIApplication(int argc, char* argv[]) : + QApplication(argc, argv) +{ + // setup the GUI + _mainWindow.show(); +} diff --git a/tools/oven/src/OvenGUIApplication.h b/tools/oven/src/OvenGUIApplication.h new file mode 100644 index 0000000000..7f5bbf3eaf --- /dev/null +++ b/tools/oven/src/OvenGUIApplication.h @@ -0,0 +1,33 @@ +// +// OvenGUIApplication.h +// tools/oven/src +// +// Created by Stephen Birarda on 2/20/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 +// + +#ifndef hifi_OvenGUIApplication_h +#define hifi_OvenGUIApplication_h + +#include + +#include "ui/OvenMainWindow.h" + +#include "Oven.h" + +class OvenGUIApplication : public QApplication, public Oven { + Q_OBJECT +public: + OvenGUIApplication(int argc, char* argv[]); + + static OvenGUIApplication* instance() { return dynamic_cast(QApplication::instance()); } + + OvenMainWindow* getMainWindow() { return &_mainWindow; } +private: + OvenMainWindow _mainWindow; +}; + +#endif // hifi_OvenGUIApplication_h diff --git a/tools/oven/src/main.cpp b/tools/oven/src/main.cpp index 3f4afe1f15..7009089402 100644 --- a/tools/oven/src/main.cpp +++ b/tools/oven/src/main.cpp @@ -8,7 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -#include "Oven.h" +#include "OvenCLIApplication.h" +#include "OvenGUIApplication.h" #include #include @@ -20,6 +21,12 @@ int main (int argc, char** argv) { // init the settings interface so we can save and load settings Setting::init(); - Oven app(argc, argv); - return app.exec(); + // figure out if we're launching our GUI application or just the simple command line interface + if (argc > 1) { + OvenCLIApplication app { argc, argv }; + return app.exec(); + } else { + OvenGUIApplication app { argc, argv }; + return app.exec(); + } } diff --git a/tools/oven/src/ui/BakeWidget.cpp b/tools/oven/src/ui/BakeWidget.cpp index 9fb8f2f880..22e1b1aaf9 100644 --- a/tools/oven/src/ui/BakeWidget.cpp +++ b/tools/oven/src/ui/BakeWidget.cpp @@ -11,8 +11,7 @@ #include -#include "../Oven.h" -#include "OvenMainWindow.h" +#include "../OvenGUIApplication.h" #include "BakeWidget.h" @@ -28,7 +27,7 @@ BakeWidget::~BakeWidget() { auto it = _bakers.begin(); while (it != _bakers.end()) { auto resultRow = it->second; - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); resultsWindow->changeStatusForRow(resultRow, "Cancelled"); diff --git a/tools/oven/src/ui/DomainBakeWidget.cpp b/tools/oven/src/ui/DomainBakeWidget.cpp index 41452c7283..bf79319458 100644 --- a/tools/oven/src/ui/DomainBakeWidget.cpp +++ b/tools/oven/src/ui/DomainBakeWidget.cpp @@ -21,8 +21,7 @@ #include #include -#include "../Oven.h" -#include "OvenMainWindow.h" +#include "../OvenGUIApplication.h" #include "DomainBakeWidget.h" @@ -223,14 +222,14 @@ void DomainBakeWidget::bakeButtonClicked() { connect(domainBaker.get(), &DomainBaker::bakeProgress, this, &DomainBakeWidget::handleBakerProgress); // move the baker to the next available Oven worker thread - auto nextThread = qApp->getNextWorkerThread(); + auto nextThread = Oven::instance().getNextWorkerThread(); domainBaker->moveToThread(nextThread); // kickoff the domain baker on its thread QMetaObject::invokeMethod(domainBaker.get(), "bake"); // add a pending row to the results window to show that this bake is in process - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); auto resultsRowName = _domainNameLineEdit->text().isEmpty() ? fileToBakeURL.fileName() : _domainNameLineEdit->text(); auto resultsRow = resultsWindow->addPendingResultRow(resultsRowName, outputDirectory); @@ -250,7 +249,7 @@ void DomainBakeWidget::handleBakerProgress(int baked, int total) { auto resultRow = it->second; // grab the results window, don't force it to be brought to the top - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(false); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(false); int percentage = roundf(float(baked) / float(total) * 100.0f); @@ -269,7 +268,7 @@ void DomainBakeWidget::handleFinishedBaker() { if (it != _bakers.end()) { auto resultRow = it->second; - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); if (baker->hasErrors()) { auto errors = baker->getErrors(); diff --git a/tools/oven/src/ui/ModelBakeWidget.cpp b/tools/oven/src/ui/ModelBakeWidget.cpp index 7963b3f3c4..61eea55917 100644 --- a/tools/oven/src/ui/ModelBakeWidget.cpp +++ b/tools/oven/src/ui/ModelBakeWidget.cpp @@ -21,8 +21,7 @@ #include #include -#include "../Oven.h" -#include "OvenMainWindow.h" +#include "../OvenGUIApplication.h" #include "ModelBakeWidget.h" @@ -208,12 +207,12 @@ void ModelBakeWidget::bakeButtonClicked() { // everything seems to be in place, kick off a bake for this model now auto baker = std::unique_ptr { new FBXBaker(modelToBakeURL, []() -> QThread* { - return qApp->getNextWorkerThread(); + return Oven::instance().getNextWorkerThread(); }, bakedOutputDirectory.absolutePath(), originalOutputDirectory.absolutePath()) }; // move the baker to the FBX baker thread - baker->moveToThread(qApp->getNextWorkerThread()); + baker->moveToThread(Oven::instance().getNextWorkerThread()); // invoke the bake method on the baker thread QMetaObject::invokeMethod(baker.get(), "bake"); @@ -222,7 +221,7 @@ void ModelBakeWidget::bakeButtonClicked() { connect(baker.get(), &FBXBaker::finished, this, &ModelBakeWidget::handleFinishedBaker); // add a pending row to the results window to show that this bake is in process - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); auto resultsRow = resultsWindow->addPendingResultRow(modelToBakeURL.fileName(), outputDirectory); // keep a unique_ptr to this baker @@ -244,7 +243,7 @@ void ModelBakeWidget::handleFinishedBaker() { if (it != _bakers.end()) { auto resultRow = it->second; - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); if (baker->hasErrors()) { resultsWindow->changeStatusForRow(resultRow, baker->getErrors().join("\n")); diff --git a/tools/oven/src/ui/SkyboxBakeWidget.cpp b/tools/oven/src/ui/SkyboxBakeWidget.cpp index cbaaa5ec0a..369b06c39f 100644 --- a/tools/oven/src/ui/SkyboxBakeWidget.cpp +++ b/tools/oven/src/ui/SkyboxBakeWidget.cpp @@ -21,8 +21,7 @@ #include #include -#include "../Oven.h" -#include "OvenMainWindow.h" +#include "../OvenGUIApplication.h" #include "SkyboxBakeWidget.h" @@ -184,7 +183,7 @@ void SkyboxBakeWidget::bakeButtonClicked() { }; // move the baker to a worker thread - baker->moveToThread(qApp->getNextWorkerThread()); + baker->moveToThread(Oven::instance().getNextWorkerThread()); // invoke the bake method on the baker thread QMetaObject::invokeMethod(baker.get(), "bake"); @@ -193,7 +192,7 @@ void SkyboxBakeWidget::bakeButtonClicked() { connect(baker.get(), &TextureBaker::finished, this, &SkyboxBakeWidget::handleFinishedBaker); // add a pending row to the results window to show that this bake is in process - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); auto resultsRow = resultsWindow->addPendingResultRow(skyboxToBakeURL.fileName(), outputDirectory); // keep a unique_ptr to this baker @@ -211,7 +210,7 @@ void SkyboxBakeWidget::handleFinishedBaker() { if (it != _bakers.end()) { auto resultRow = it->second; - auto resultsWindow = qApp->getMainWindow()->showResultsWindow(); + auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow(); if (baker->hasErrors()) { resultsWindow->changeStatusForRow(resultRow, baker->getErrors().join("\n"));