mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
Merge branch 'workload' of https://github.com/highfidelity/hifi into workload
This commit is contained in:
commit
ceb38dbc97
33 changed files with 550 additions and 137 deletions
|
@ -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}";
|
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<HTTPConnection> connectionPtr { connection };
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||||
|
|
||||||
auto getSetting = [this](QString keyPath, QVariant value) -> bool {
|
auto getSetting = [this](QString keyPath, QVariant& value) -> bool {
|
||||||
|
|
||||||
value = _settingsManager.valueForKeyPath(keyPath);
|
value = _settingsManager.valueForKeyPath(keyPath);
|
||||||
if (!value.isValid()) {
|
if (!value.isValid()) {
|
||||||
|
@ -2120,30 +2122,38 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
||||||
return true;
|
return true;
|
||||||
} else if (url.path() == URI_API_BACKUPS) {
|
} else if (url.path() == URI_API_BACKUPS) {
|
||||||
auto deferred = makePromise("getAllBackupsAndStatus");
|
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));
|
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);
|
_contentManager->getAllBackupsAndStatus(deferred);
|
||||||
return true;
|
return true;
|
||||||
} else if (url.path().startsWith(URI_API_BACKUPS_ID)) {
|
} else if (url.path().startsWith(URI_API_BACKUPS_ID)) {
|
||||||
auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length());
|
auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length());
|
||||||
auto deferred = makePromise("consolidateBackup");
|
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;
|
QJsonObject rootJSON;
|
||||||
auto success = result["success"].toBool();
|
auto success = result["success"].toBool();
|
||||||
if (success) {
|
if (success) {
|
||||||
auto path = result["backupFilePath"].toString();
|
auto path = result["backupFilePath"].toString();
|
||||||
auto file { std::unique_ptr<QFile>(new QFile(path)) };
|
auto file { std::unique_ptr<QFile>(new QFile(path)) };
|
||||||
if (file->open(QIODevice::ReadOnly)) {
|
if (file->open(QIODevice::ReadOnly)) {
|
||||||
connection->respond(HTTPConnection::StatusCode200, std::move(file));
|
connectionPtr->respond(HTTPConnection::StatusCode200, std::move(file));
|
||||||
} else {
|
} else {
|
||||||
qCritical(domain_server) << "Unable to load consolidated backup at:" << path << result;
|
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 {
|
} else {
|
||||||
connection->respond(HTTPConnection::StatusCode400);
|
connectionPtr->respond(HTTPConnection::StatusCode400);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_contentManager->consolidateBackup(deferred, id);
|
_contentManager->consolidateBackup(deferred, id);
|
||||||
|
@ -2264,12 +2274,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
||||||
} else if (uploadedFilename.endsWith(".zip", Qt::CaseInsensitive)) {
|
} else if (uploadedFilename.endsWith(".zip", Qt::CaseInsensitive)) {
|
||||||
auto deferred = makePromise("recoverFromUploadedBackup");
|
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;
|
QJsonObject rootJSON;
|
||||||
auto success = result["success"].toBool();
|
auto success = result["success"].toBool();
|
||||||
rootJSON["success"] = success;
|
rootJSON["success"] = success;
|
||||||
QJsonDocument docJSON(rootJSON);
|
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());
|
JSON_MIME_TYPE.toUtf8());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2297,12 +2311,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
||||||
}
|
}
|
||||||
|
|
||||||
auto deferred = makePromise("createManualBackup");
|
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;
|
QJsonObject rootJSON;
|
||||||
auto success = result["success"].toBool();
|
auto success = result["success"].toBool();
|
||||||
rootJSON["success"] = success;
|
rootJSON["success"] = success;
|
||||||
QJsonDocument docJSON(rootJSON);
|
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());
|
JSON_MIME_TYPE.toUtf8());
|
||||||
});
|
});
|
||||||
_contentManager->createManualBackup(deferred, it.value());
|
_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)) {
|
} else if (url.path().startsWith(URI_API_BACKUPS_RECOVER)) {
|
||||||
auto id = url.path().mid(QString(URI_API_BACKUPS_RECOVER).length());
|
auto id = url.path().mid(QString(URI_API_BACKUPS_RECOVER).length());
|
||||||
auto deferred = makePromise("recoverFromBackup");
|
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;
|
QJsonObject rootJSON;
|
||||||
auto success = result["success"].toBool();
|
auto success = result["success"].toBool();
|
||||||
rootJSON["success"] = success;
|
rootJSON["success"] = success;
|
||||||
QJsonDocument docJSON(rootJSON);
|
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());
|
JSON_MIME_TYPE.toUtf8());
|
||||||
});
|
});
|
||||||
_contentManager->recoverFromBackup(deferred, id);
|
_contentManager->recoverFromBackup(deferred, id);
|
||||||
|
@ -2423,12 +2445,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
||||||
if (url.path().startsWith(URI_API_BACKUPS_ID)) {
|
if (url.path().startsWith(URI_API_BACKUPS_ID)) {
|
||||||
auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length());
|
auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length());
|
||||||
auto deferred = makePromise("deleteBackup");
|
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;
|
QJsonObject rootJSON;
|
||||||
auto success = result["success"].toBool();
|
auto success = result["success"].toBool();
|
||||||
rootJSON["success"] = success;
|
rootJSON["success"] = success;
|
||||||
QJsonDocument docJSON(rootJSON);
|
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());
|
JSON_MIME_TYPE.toUtf8());
|
||||||
});
|
});
|
||||||
_contentManager->deleteBackup(deferred, id);
|
_contentManager->deleteBackup(deferred, id);
|
||||||
|
|
|
@ -681,5 +681,9 @@ scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() {
|
||||||
}
|
}
|
||||||
auto result = _model->getScriptableModel();
|
auto result = _model->getScriptableModel();
|
||||||
result.objectID = getID();
|
result.objectID = getID();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||||
|
result.appendMaterials(_materials);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1801,5 +1801,9 @@ scriptable::ScriptableModelBase Avatar::getScriptableModel() {
|
||||||
}
|
}
|
||||||
auto result = _skeletonModel->getScriptableModel();
|
auto result = _skeletonModel->getScriptableModel();
|
||||||
result.objectID = getSessionUUID().isNull() ? AVATAR_SELF_ID : getSessionUUID();
|
result.objectID = getSessionUUID().isNull() ? AVATAR_SELF_ID : getSessionUUID();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||||
|
result.appendMaterials(_materials);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
|
@ -974,6 +974,10 @@ scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScript
|
||||||
|
|
||||||
auto result = _model->getScriptableModel();
|
auto result = _model->getScriptableModel();
|
||||||
result.objectID = getEntity()->getID();
|
result.objectID = getEntity()->getID();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||||
|
result.appendMaterials(_materials);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,8 +169,12 @@ scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel() {
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
auto geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
auto geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||||
glm::vec3 vertexColor;
|
glm::vec3 vertexColor;
|
||||||
if (_materials["0"].top().material) {
|
{
|
||||||
vertexColor = _materials["0"].top().material->getAlbedo();
|
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||||
|
result.appendMaterials(_materials);
|
||||||
|
if (_materials["0"].top().material) {
|
||||||
|
vertexColor = _materials["0"].top().material->getAlbedo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) {
|
if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) {
|
||||||
result.objectID = getEntity()->getID();
|
result.objectID = getEntity()->getID();
|
||||||
|
|
|
@ -868,16 +868,6 @@ void SphericalHarmonics::evalFromTexture(const Texture& texture) {
|
||||||
|
|
||||||
|
|
||||||
// TextureSource
|
// TextureSource
|
||||||
TextureSource::TextureSource() {
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureSource::~TextureSource() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureSource::reset(const QUrl& url) {
|
|
||||||
_imageUrl = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureSource::resetTexture(gpu::TexturePointer texture) {
|
void TextureSource::resetTexture(gpu::TexturePointer texture) {
|
||||||
_gpuTexture = texture;
|
_gpuTexture = texture;
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,13 +647,11 @@ typedef std::vector<TextureView> TextureViews;
|
||||||
// It provides the mechanism to create a texture using a customizable TextureLoader
|
// It provides the mechanism to create a texture using a customizable TextureLoader
|
||||||
class TextureSource {
|
class TextureSource {
|
||||||
public:
|
public:
|
||||||
TextureSource();
|
TextureSource(const QUrl& url, int type = 0) : _imageUrl(url), _type(type) {}
|
||||||
~TextureSource();
|
|
||||||
|
|
||||||
const QUrl& getUrl() const { return _imageUrl; }
|
const QUrl& getUrl() const { return _imageUrl; }
|
||||||
const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; }
|
const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; }
|
||||||
|
int getType() const { return _type; }
|
||||||
void reset(const QUrl& url);
|
|
||||||
|
|
||||||
void resetTexture(gpu::TexturePointer texture);
|
void resetTexture(gpu::TexturePointer texture);
|
||||||
|
|
||||||
|
@ -662,6 +660,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
gpu::TexturePointer _gpuTexture;
|
gpu::TexturePointer _gpuTexture;
|
||||||
QUrl _imageUrl;
|
QUrl _imageUrl;
|
||||||
|
int _type { 0 };
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr< TextureSource > TextureSourcePointer;
|
typedef std::shared_ptr< TextureSource > TextureSourcePointer;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
set(TARGET_NAME graphics-scripting)
|
set(TARGET_NAME graphics-scripting)
|
||||||
setup_hifi_library()
|
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)
|
include_hifi_library_headers(gpu)
|
||||||
|
|
|
@ -6,9 +6,14 @@
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <SpatiallyNestable.h>
|
#include <SpatiallyNestable.h>
|
||||||
|
|
||||||
|
#include "graphics/Material.h"
|
||||||
|
#include "graphics/TextureMap.h"
|
||||||
|
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
class Mesh;
|
class Mesh;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +36,53 @@ namespace scriptable {
|
||||||
using ModelProviderPointer = std::shared_ptr<scriptable::ModelProvider>;
|
using ModelProviderPointer = std::shared_ptr<scriptable::ModelProvider>;
|
||||||
using WeakModelProviderPointer = std::weak_ptr<scriptable::ModelProvider>;
|
using WeakModelProviderPointer = std::weak_ptr<scriptable::ModelProvider>;
|
||||||
|
|
||||||
|
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<QString, QVector<scriptable::ScriptableMaterialLayer>> MultiMaterialMap;
|
||||||
|
|
||||||
class ScriptableMeshBase : public QObject {
|
class ScriptableMeshBase : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -55,6 +107,8 @@ namespace scriptable {
|
||||||
WeakModelProviderPointer provider;
|
WeakModelProviderPointer provider;
|
||||||
QUuid objectID; // spatially nestable ID
|
QUuid objectID; // spatially nestable ID
|
||||||
QVector<scriptable::ScriptableMeshBase> meshes;
|
QVector<scriptable::ScriptableMeshBase> meshes;
|
||||||
|
MultiMaterialMap materialLayers;
|
||||||
|
QVector<QString> materialNames;
|
||||||
|
|
||||||
ScriptableModelBase(QObject* parent = nullptr) : QObject(parent) {}
|
ScriptableModelBase(QObject* parent = nullptr) : QObject(parent) {}
|
||||||
ScriptableModelBase(const ScriptableModelBase& other) : QObject(other.parent()) { *this = other; }
|
ScriptableModelBase(const ScriptableModelBase& other) : QObject(other.parent()) { *this = other; }
|
||||||
|
@ -63,9 +117,11 @@ namespace scriptable {
|
||||||
|
|
||||||
void append(const ScriptableMeshBase& mesh);
|
void append(const ScriptableMeshBase& mesh);
|
||||||
void append(scriptable::WeakMeshPointer mesh);
|
void append(scriptable::WeakMeshPointer mesh);
|
||||||
|
void appendMaterial(const graphics::MaterialLayer& materialLayer, int shapeID, std::string materialName);
|
||||||
|
void appendMaterials(const std::unordered_map<std::string, graphics::MultiMaterial>& materialsToAppend);
|
||||||
|
void appendMaterialNames(const std::vector<std::string>& names);
|
||||||
// TODO: in future containers for these could go here
|
// TODO: in future containers for these could go here
|
||||||
// QVariantMap shapes;
|
// QVariantMap shapes;
|
||||||
// QVariantMap materials;
|
|
||||||
// QVariantMap armature;
|
// QVariantMap armature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -297,6 +297,10 @@ namespace {
|
||||||
qRegisterMetaType<scriptable::ScriptableMeshPointer>(),
|
qRegisterMetaType<scriptable::ScriptableMeshPointer>(),
|
||||||
qRegisterMetaType<scriptable::ScriptableModelPointer>(),
|
qRegisterMetaType<scriptable::ScriptableModelPointer>(),
|
||||||
qRegisterMetaType<scriptable::ScriptableMeshPartPointer>(),
|
qRegisterMetaType<scriptable::ScriptableMeshPartPointer>(),
|
||||||
|
qRegisterMetaType<scriptable::ScriptableMaterial>(),
|
||||||
|
qRegisterMetaType<scriptable::ScriptableMaterialLayer>(),
|
||||||
|
qRegisterMetaType<QVector<scriptable::ScriptableMaterialLayer>>(),
|
||||||
|
qRegisterMetaType<scriptable::MultiMaterialMap>(),
|
||||||
qRegisterMetaType<graphics::Mesh::Topology>(),
|
qRegisterMetaType<graphics::Mesh::Topology>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -335,6 +339,67 @@ namespace scriptable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValue qVectorScriptableMaterialLayerToScriptValue(QScriptEngine* engine, const QVector<scriptable::ScriptableMaterialLayer>& vector) {
|
||||||
|
return qScriptValueFromSequence(engine, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qVectorScriptableMaterialLayerFromScriptValue(const QScriptValue& array, QVector<scriptable::ScriptableMaterialLayer>& 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 <typename T> int registerDebugEnum(QScriptEngine* engine, const DebugEnums<T>& debugEnums) {
|
template <typename T> int registerDebugEnum(QScriptEngine* engine, const DebugEnums<T>& debugEnums) {
|
||||||
static const DebugEnums<T>& instance = debugEnums;
|
static const DebugEnums<T>& instance = debugEnums;
|
||||||
return qScriptRegisterMetaType<T>(
|
return qScriptRegisterMetaType<T>(
|
||||||
|
@ -351,6 +416,7 @@ namespace scriptable {
|
||||||
|
|
||||||
void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
|
void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
|
||||||
qScriptRegisterSequenceMetaType<QVector<glm::uint32>>(engine);
|
qScriptRegisterSequenceMetaType<QVector<glm::uint32>>(engine);
|
||||||
|
qScriptRegisterSequenceMetaType<QVector<scriptable::ScriptableMaterialLayer>>(engine);
|
||||||
|
|
||||||
scriptable::registerQPointerMetaType<scriptable::ScriptableModel>(engine);
|
scriptable::registerQPointerMetaType<scriptable::ScriptableModel>(engine);
|
||||||
scriptable::registerQPointerMetaType<scriptable::ScriptableMesh>(engine);
|
scriptable::registerQPointerMetaType<scriptable::ScriptableMesh>(engine);
|
||||||
|
@ -361,6 +427,11 @@ void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
|
||||||
scriptable::registerDebugEnum<gpu::Semantic>(engine, gpu::SEMANTICS);
|
scriptable::registerDebugEnum<gpu::Semantic>(engine, gpu::SEMANTICS);
|
||||||
scriptable::registerDebugEnum<gpu::Dimension>(engine, gpu::DIMENSIONS);
|
scriptable::registerDebugEnum<gpu::Dimension>(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);
|
Q_UNUSED(metaTypeIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -400,6 +400,5 @@ scriptable::ScriptableMesh::~ScriptableMesh() {
|
||||||
strongMesh.reset();
|
strongMesh.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "ScriptableMesh.moc"
|
#include "ScriptableMesh.moc"
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,120 @@
|
||||||
|
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
|
#include "graphics/Material.h"
|
||||||
|
|
||||||
|
#include "image/Image.h"
|
||||||
|
|
||||||
// #define SCRIPTABLE_MESH_DEBUG 1
|
// #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) {
|
scriptable::ScriptableModelBase& scriptable::ScriptableModelBase::operator=(const scriptable::ScriptableModelBase& other) {
|
||||||
provider = other.provider;
|
provider = other.provider;
|
||||||
objectID = other.objectID;
|
objectID = other.objectID;
|
||||||
for (const auto& mesh : other.meshes) {
|
for (const auto& mesh : other.meshes) {
|
||||||
append(mesh);
|
append(mesh);
|
||||||
}
|
}
|
||||||
|
materialLayers = other.materialLayers;
|
||||||
|
materialNames = other.materialNames;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +140,8 @@ scriptable::ScriptableModelBase::~ScriptableModelBase() {
|
||||||
m.strongMesh.reset();
|
m.strongMesh.reset();
|
||||||
}
|
}
|
||||||
meshes.clear();
|
meshes.clear();
|
||||||
|
materialLayers.clear();
|
||||||
|
materialNames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptable::ScriptableModelBase::append(scriptable::WeakMeshPointer mesh) {
|
void scriptable::ScriptableModelBase::append(scriptable::WeakMeshPointer mesh) {
|
||||||
|
@ -47,6 +155,27 @@ void scriptable::ScriptableModelBase::append(const ScriptableMeshBase& mesh) {
|
||||||
meshes << 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<std::string, graphics::MultiMaterial>& 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<std::string>& names) {
|
||||||
|
for (auto& name : names) {
|
||||||
|
materialNames.append(QString::fromStdString(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString scriptable::ScriptableModel::toString() const {
|
QString scriptable::ScriptableModel::toString() const {
|
||||||
return QString("[ScriptableModel%1%2 numMeshes=%3]")
|
return QString("[ScriptableModel%1%2 numMeshes=%3]")
|
||||||
.arg(objectID.isNull() ? "" : " objectID="+objectID.toString())
|
.arg(objectID.isNull() ? "" : " objectID="+objectID.toString())
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace scriptable {
|
||||||
* @property {Uuid} objectID - UUID of corresponding inworld object (if model is associated)
|
* @property {Uuid} objectID - UUID of corresponding inworld object (if model is associated)
|
||||||
* @property {number} numMeshes - The number of submeshes contained in the model.
|
* @property {number} numMeshes - The number of submeshes contained in the model.
|
||||||
* @property {Graphics.Mesh[]} meshes - Array of submesh references.
|
* @property {Graphics.Mesh[]} meshes - Array of submesh references.
|
||||||
|
* @property {Object.<string, Graphics.MaterialLayer[]>} 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 {
|
class ScriptableModel : public ScriptableModelBase {
|
||||||
|
@ -28,18 +30,24 @@ namespace scriptable {
|
||||||
Q_PROPERTY(QUuid objectID MEMBER objectID CONSTANT)
|
Q_PROPERTY(QUuid objectID MEMBER objectID CONSTANT)
|
||||||
Q_PROPERTY(glm::uint32 numMeshes READ getNumMeshes)
|
Q_PROPERTY(glm::uint32 numMeshes READ getNumMeshes)
|
||||||
Q_PROPERTY(ScriptableMeshes meshes READ getMeshes)
|
Q_PROPERTY(ScriptableMeshes meshes READ getMeshes)
|
||||||
|
Q_PROPERTY(scriptable::MultiMaterialMap materialLayers READ getMaterialLayers)
|
||||||
|
Q_PROPERTY(QVector<QString> materialNames READ getMaterialNames)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScriptableModel(QObject* parent = nullptr) : ScriptableModelBase(parent) {}
|
ScriptableModel(QObject* parent = nullptr) : ScriptableModelBase(parent) {}
|
||||||
ScriptableModel(const ScriptableModel& other) : ScriptableModelBase(other) {}
|
ScriptableModel(const ScriptableModel& other) : ScriptableModelBase(other) {}
|
||||||
ScriptableModel(const ScriptableModelBase& other) : ScriptableModelBase(other) {}
|
ScriptableModel(const ScriptableModelBase& other) : ScriptableModelBase(other) {}
|
||||||
ScriptableModel& operator=(const ScriptableModelBase& view) { ScriptableModelBase::operator=(view); return *this; }
|
ScriptableModel& operator=(const ScriptableModelBase& view) { ScriptableModelBase::operator=(view); return *this; }
|
||||||
|
|
||||||
operator scriptable::ScriptableModelBasePointer() {
|
operator scriptable::ScriptableModelBasePointer() {
|
||||||
return QPointer<scriptable::ScriptableModelBase>(qobject_cast<scriptable::ScriptableModelBase*>(this));
|
return QPointer<scriptable::ScriptableModelBase>(qobject_cast<scriptable::ScriptableModelBase*>(this));
|
||||||
}
|
}
|
||||||
ScriptableMeshes getMeshes();
|
ScriptableMeshes getMeshes();
|
||||||
const ScriptableMeshes getConstMeshes() const;
|
const ScriptableMeshes getConstMeshes() const;
|
||||||
|
|
||||||
|
scriptable::MultiMaterialMap getMaterialLayers() { return materialLayers; }
|
||||||
|
QVector<QString> getMaterialNames() { return materialNames; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap());
|
scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap());
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
@ -53,3 +61,6 @@ namespace scriptable {
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(scriptable::ScriptableModelPointer)
|
Q_DECLARE_METATYPE(scriptable::ScriptableModelPointer)
|
||||||
Q_DECLARE_METATYPE(QVector<scriptable::ScriptableModelPointer>)
|
Q_DECLARE_METATYPE(QVector<scriptable::ScriptableModelPointer>)
|
||||||
|
Q_DECLARE_METATYPE(scriptable::ScriptableMaterial)
|
||||||
|
Q_DECLARE_METATYPE(scriptable::ScriptableMaterialLayer)
|
||||||
|
Q_DECLARE_METATYPE(scriptable::MultiMaterialMap)
|
||||||
|
|
|
@ -356,8 +356,9 @@ public:
|
||||||
|
|
||||||
void setTextureTransforms(const Transform& transform);
|
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; }
|
void setModel(const std::string& model) { _model = model; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include "QJsonDocument"
|
#include "QJsonDocument"
|
||||||
#include "QJsonArray"
|
#include "QJsonArray"
|
||||||
|
|
||||||
|
#include "RegisteredMetaTypes.h"
|
||||||
|
|
||||||
NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) :
|
NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) :
|
||||||
Resource(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());
|
color = glm::vec3(colorArray[0].toDouble(), colorArray[1].toDouble(), colorArray[2].toDouble());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if (array.isObject()) {
|
||||||
|
bool toReturn;
|
||||||
|
isSRGB = true;
|
||||||
|
color = vec3FromVariant(array.toObject(), toReturn);
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,7 +294,7 @@ _type(),
|
||||||
_sourceIsKTX(false),
|
_sourceIsKTX(false),
|
||||||
_maxNumPixels(100)
|
_maxNumPixels(100)
|
||||||
{
|
{
|
||||||
_textureSource = std::make_shared<gpu::TextureSource>();
|
_textureSource = std::make_shared<gpu::TextureSource>(url);
|
||||||
_lowestRequestedMipLevel = 0;
|
_lowestRequestedMipLevel = 0;
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type,
|
||||||
_sourceIsKTX(url.path().endsWith(".ktx")),
|
_sourceIsKTX(url.path().endsWith(".ktx")),
|
||||||
_maxNumPixels(maxNumPixels)
|
_maxNumPixels(maxNumPixels)
|
||||||
{
|
{
|
||||||
_textureSource = std::make_shared<gpu::TextureSource>();
|
_textureSource = std::make_shared<gpu::TextureSource>(url, (int)type);
|
||||||
_lowestRequestedMipLevel = 0;
|
_lowestRequestedMipLevel = 0;
|
||||||
|
|
||||||
_shouldFailOnRedirect = !_sourceIsKTX;
|
_shouldFailOnRedirect = !_sourceIsKTX;
|
||||||
|
|
|
@ -578,6 +578,7 @@ void Connection::processControl(ControlPacketPointer controlPacket) {
|
||||||
#ifdef UDT_CONNECTION_DEBUG
|
#ifdef UDT_CONNECTION_DEBUG
|
||||||
qCDebug(networking) << "Got handshake request, stopping SendQueue";
|
qCDebug(networking) << "Got handshake request, stopping SendQueue";
|
||||||
#endif
|
#endif
|
||||||
|
_hasReceivedHandshakeACK = false;
|
||||||
stopSendQueue();
|
stopSendQueue();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -62,6 +62,7 @@ void CauterizedModel::createVisibleRenderItemSet() {
|
||||||
Q_ASSERT(_modelMeshRenderItems.isEmpty());
|
Q_ASSERT(_modelMeshRenderItems.isEmpty());
|
||||||
|
|
||||||
_modelMeshRenderItems.clear();
|
_modelMeshRenderItems.clear();
|
||||||
|
_modelMeshMaterialNames.clear();
|
||||||
_modelMeshRenderItemShapes.clear();
|
_modelMeshRenderItemShapes.clear();
|
||||||
|
|
||||||
Transform transform;
|
Transform transform;
|
||||||
|
@ -86,6 +87,7 @@ void CauterizedModel::createVisibleRenderItemSet() {
|
||||||
for (int partIndex = 0; partIndex < numParts; partIndex++) {
|
for (int partIndex = 0; partIndex < numParts; partIndex++) {
|
||||||
auto ptr = std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
|
auto ptr = std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
|
||||||
_modelMeshRenderItems << std::static_pointer_cast<ModelMeshPartPayload>(ptr);
|
_modelMeshRenderItems << std::static_pointer_cast<ModelMeshPartPayload>(ptr);
|
||||||
|
_modelMeshMaterialNames.push_back(getGeometry()->getShapeMaterial(shapeID)->getName());
|
||||||
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
|
_modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i });
|
||||||
shapeID++;
|
shapeID++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -684,12 +684,20 @@ scriptable::ScriptableModelBase Model::getScriptableModel() {
|
||||||
|
|
||||||
const FBXGeometry& geometry = getFBXGeometry();
|
const FBXGeometry& geometry = getFBXGeometry();
|
||||||
int numberOfMeshes = geometry.meshes.size();
|
int numberOfMeshes = geometry.meshes.size();
|
||||||
|
int shapeID = 0;
|
||||||
for (int i = 0; i < numberOfMeshes; i++) {
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
const FBXMesh& fbxMesh = geometry.meshes.at(i);
|
const FBXMesh& fbxMesh = geometry.meshes.at(i);
|
||||||
if (auto mesh = fbxMesh._mesh) {
|
if (auto mesh = fbxMesh._mesh) {
|
||||||
result.append(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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,14 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
|
#include "OvenCLIApplication.h"
|
||||||
#include "ModelBakingLoggingCategory.h"
|
#include "ModelBakingLoggingCategory.h"
|
||||||
#include "Oven.h"
|
|
||||||
#include "BakerCLI.h"
|
#include "BakerCLI.h"
|
||||||
#include "FBXBaker.h"
|
#include "FBXBaker.h"
|
||||||
#include "TextureBaker.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) {
|
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
|
// create our appropiate baker
|
||||||
if (isFBX) {
|
if (isFBX) {
|
||||||
_baker = std::unique_ptr<Baker> { new FBXBaker(inputUrl, []() -> QThread* { return qApp->getNextWorkerThread(); }, outputPath) };
|
_baker = std::unique_ptr<Baker> {
|
||||||
_baker->moveToThread(qApp->getNextWorkerThread());
|
new FBXBaker(inputUrl,
|
||||||
|
[]() -> QThread* { return Oven::instance().getNextWorkerThread(); },
|
||||||
|
outputPath)
|
||||||
|
};
|
||||||
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
} else if (isSupportedImage) {
|
} else if (isSupportedImage) {
|
||||||
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) };
|
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) };
|
||||||
_baker->moveToThread(qApp->getNextWorkerThread());
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
} else {
|
} else {
|
||||||
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
||||||
QApplication::exit(OVEN_STATUS_CODE_FAIL);
|
QCoreApplication::exit(OVEN_STATUS_CODE_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// invoke the bake method on the baker thread
|
// invoke the bake method on the baker thread
|
||||||
|
@ -81,5 +86,5 @@ void BakerCLI::handleFinishedBaker() {
|
||||||
errorFile.close();
|
errorFile.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QApplication::exit(exitCode);
|
QCoreApplication::exit(exitCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Baker.h"
|
#include "Baker.h"
|
||||||
#include "Oven.h"
|
#include "OvenCLIApplication.h"
|
||||||
|
|
||||||
static const int OVEN_STATUS_CODE_SUCCESS { 0 };
|
static const int OVEN_STATUS_CODE_SUCCESS { 0 };
|
||||||
static const int OVEN_STATUS_CODE_FAIL { 1 };
|
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";
|
static const QString OVEN_ERROR_FILENAME = "errors.txt";
|
||||||
|
|
||||||
class BakerCLI : public QObject {
|
class BakerCLI : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BakerCLI(Oven* parent);
|
BakerCLI(OvenCLIApplication* parent);
|
||||||
void bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type = QString::null);
|
void bakeFile(QUrl inputUrl, const QString& outputPath, const QString& type = QString::null);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -201,7 +201,7 @@ void DomainBaker::enumerateEntities() {
|
||||||
}
|
}
|
||||||
QSharedPointer<FBXBaker> baker {
|
QSharedPointer<FBXBaker> baker {
|
||||||
new FBXBaker(modelURL, []() -> QThread* {
|
new FBXBaker(modelURL, []() -> QThread* {
|
||||||
return qApp->getNextWorkerThread();
|
return Oven::instance().getNextWorkerThread();
|
||||||
}, _contentOutputPath + subDirName + "/baked", _contentOutputPath + subDirName + "/original"),
|
}, _contentOutputPath + subDirName + "/baked", _contentOutputPath + subDirName + "/original"),
|
||||||
&FBXBaker::deleteLater
|
&FBXBaker::deleteLater
|
||||||
};
|
};
|
||||||
|
@ -214,7 +214,7 @@ void DomainBaker::enumerateEntities() {
|
||||||
|
|
||||||
// move the baker to the baker thread
|
// move the baker to the baker thread
|
||||||
// and kickoff the bake
|
// and kickoff the bake
|
||||||
baker->moveToThread(qApp->getNextWorkerThread());
|
baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
QMetaObject::invokeMethod(baker.data(), "bake");
|
QMetaObject::invokeMethod(baker.data(), "bake");
|
||||||
|
|
||||||
// keep track of the total number of baking entities
|
// keep track of the total number of baking entities
|
||||||
|
@ -285,7 +285,7 @@ void DomainBaker::bakeSkybox(QUrl skyboxURL, QJsonValueRef entity) {
|
||||||
_skyboxBakers.insert(skyboxURL, skyboxBaker);
|
_skyboxBakers.insert(skyboxURL, skyboxBaker);
|
||||||
|
|
||||||
// move the baker to a worker thread and kickoff the bake
|
// 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");
|
QMetaObject::invokeMethod(skyboxBaker.data(), "bake");
|
||||||
|
|
||||||
// keep track of the total number of baking entities
|
// keep track of the total number of baking entities
|
||||||
|
|
|
@ -11,33 +11,15 @@
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QCommandLineParser>
|
|
||||||
|
|
||||||
#include <image/Image.h>
|
#include <image/Image.h>
|
||||||
|
|
||||||
#include "ui/OvenMainWindow.h"
|
|
||||||
#include "Oven.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";
|
Oven::Oven() {
|
||||||
static const QString CLI_OUTPUT_PARAMETER = "o";
|
_staticInstance = this;
|
||||||
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);
|
|
||||||
|
|
||||||
// enable compression in image library
|
// enable compression in image library
|
||||||
image::setColorTexturesCompressionEnabled(true);
|
image::setColorTexturesCompressionEnabled(true);
|
||||||
|
@ -47,41 +29,30 @@ Oven::Oven(int argc, char* argv[]) :
|
||||||
|
|
||||||
// setup our worker threads
|
// setup our worker threads
|
||||||
setupWorkerThreads(QThread::idealThreadCount());
|
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() {
|
Oven::~Oven() {
|
||||||
// cleanup the worker threads
|
// quit all worker threads and wait on them
|
||||||
for (auto i = 0; i < _workerThreads.size(); ++i) {
|
for (auto& thread : _workerThreads) {
|
||||||
_workerThreads[i]->quit();
|
thread->quit();
|
||||||
_workerThreads[i]->wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& thread: _workerThreads) {
|
||||||
|
thread->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
_staticInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Oven::setupWorkerThreads(int numWorkerThreads) {
|
void Oven::setupWorkerThreads(int numWorkerThreads) {
|
||||||
|
_workerThreads.reserve(numWorkerThreads);
|
||||||
|
|
||||||
for (auto i = 0; i < numWorkerThreads; ++i) {
|
for (auto i = 0; i < numWorkerThreads; ++i) {
|
||||||
// setup a worker thread yet and add it to our concurrent vector
|
// setup a worker thread yet and add it to our concurrent vector
|
||||||
auto newThread = new QThread(this);
|
auto newThread = std::unique_ptr<QThread> { new QThread };
|
||||||
newThread->setObjectName("Oven Worker Thread " + QString::number(i + 1));
|
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.
|
// (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 nextIndex = ++_nextWorkerThreadIndex;
|
||||||
auto nextThread = _workerThreads[nextIndex % _workerThreads.size()];
|
auto& nextThread = _workerThreads[nextIndex % _workerThreads.size()];
|
||||||
|
|
||||||
// start the thread if it isn't running yet
|
// start the thread if it isn't running yet
|
||||||
if (!nextThread->isRunning()) {
|
if (!nextThread->isRunning()) {
|
||||||
nextThread->start();
|
nextThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nextThread;
|
return nextThread.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,27 +12,16 @@
|
||||||
#ifndef hifi_Oven_h
|
#ifndef hifi_Oven_h
|
||||||
#define hifi_Oven_h
|
#define hifi_Oven_h
|
||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
|
||||||
|
|
||||||
#include <TBBHelpers.h>
|
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#if defined(qApp)
|
class Oven {
|
||||||
#undef qApp
|
|
||||||
#endif
|
|
||||||
#define qApp (static_cast<Oven*>(QCoreApplication::instance()))
|
|
||||||
|
|
||||||
class OvenMainWindow;
|
|
||||||
|
|
||||||
class Oven : public QApplication {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Oven(int argc, char* argv[]);
|
Oven();
|
||||||
~Oven();
|
~Oven();
|
||||||
|
|
||||||
OvenMainWindow* getMainWindow() const { return _mainWindow; }
|
static Oven& instance() { return *_staticInstance; }
|
||||||
|
|
||||||
QThread* getNextWorkerThread();
|
QThread* getNextWorkerThread();
|
||||||
|
|
||||||
|
@ -40,11 +29,12 @@ private:
|
||||||
void setupWorkerThreads(int numWorkerThreads);
|
void setupWorkerThreads(int numWorkerThreads);
|
||||||
void setupFBXBakerThread();
|
void setupFBXBakerThread();
|
||||||
|
|
||||||
OvenMainWindow* _mainWindow;
|
std::vector<std::unique_ptr<QThread>> _workerThreads;
|
||||||
QList<QThread*> _workerThreads;
|
|
||||||
|
|
||||||
std::atomic<uint> _nextWorkerThreadIndex;
|
std::atomic<uint> _nextWorkerThreadIndex;
|
||||||
int _numWorkerThreads;
|
int _numWorkerThreads;
|
||||||
|
|
||||||
|
static Oven* _staticInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
49
tools/oven/src/OvenCLIApplication.cpp
Normal file
49
tools/oven/src/OvenCLIApplication.cpp
Normal file
|
@ -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 <QtCore/QCommandLineParser>
|
||||||
|
#include <QtCore/QUrl>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
tools/oven/src/OvenCLIApplication.h
Normal file
27
tools/oven/src/OvenCLIApplication.h
Normal file
|
@ -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 <QtCore/QCoreApplication>
|
||||||
|
|
||||||
|
#include "Oven.h"
|
||||||
|
|
||||||
|
class OvenCLIApplication : public QCoreApplication, public Oven {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
OvenCLIApplication(int argc, char* argv[]);
|
||||||
|
|
||||||
|
static OvenCLIApplication* instance() { return dynamic_cast<OvenCLIApplication*>(QCoreApplication::instance()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_OvenCLIApplication_h
|
19
tools/oven/src/OvenGUIApplication.cpp
Normal file
19
tools/oven/src/OvenGUIApplication.cpp
Normal file
|
@ -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();
|
||||||
|
}
|
33
tools/oven/src/OvenGUIApplication.h
Normal file
33
tools/oven/src/OvenGUIApplication.h
Normal file
|
@ -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 <QtWidgets/QApplication>
|
||||||
|
|
||||||
|
#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<OvenGUIApplication*>(QApplication::instance()); }
|
||||||
|
|
||||||
|
OvenMainWindow* getMainWindow() { return &_mainWindow; }
|
||||||
|
private:
|
||||||
|
OvenMainWindow _mainWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_OvenGUIApplication_h
|
|
@ -8,7 +8,8 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// 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 <BuildInfo.h>
|
#include <BuildInfo.h>
|
||||||
#include <SettingInterface.h>
|
#include <SettingInterface.h>
|
||||||
|
@ -20,6 +21,12 @@ int main (int argc, char** argv) {
|
||||||
// init the settings interface so we can save and load settings
|
// init the settings interface so we can save and load settings
|
||||||
Setting::init();
|
Setting::init();
|
||||||
|
|
||||||
Oven app(argc, argv);
|
// figure out if we're launching our GUI application or just the simple command line interface
|
||||||
return app.exec();
|
if (argc > 1) {
|
||||||
|
OvenCLIApplication app { argc, argv };
|
||||||
|
return app.exec();
|
||||||
|
} else {
|
||||||
|
OvenGUIApplication app { argc, argv };
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
|
|
||||||
#include <QtWidgets/QStackedWidget>
|
#include <QtWidgets/QStackedWidget>
|
||||||
|
|
||||||
#include "../Oven.h"
|
#include "../OvenGUIApplication.h"
|
||||||
#include "OvenMainWindow.h"
|
|
||||||
|
|
||||||
#include "BakeWidget.h"
|
#include "BakeWidget.h"
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ BakeWidget::~BakeWidget() {
|
||||||
auto it = _bakers.begin();
|
auto it = _bakers.begin();
|
||||||
while (it != _bakers.end()) {
|
while (it != _bakers.end()) {
|
||||||
auto resultRow = it->second;
|
auto resultRow = it->second;
|
||||||
auto resultsWindow = qApp->getMainWindow()->showResultsWindow();
|
auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow();
|
||||||
|
|
||||||
resultsWindow->changeStatusForRow(resultRow, "Cancelled");
|
resultsWindow->changeStatusForRow(resultRow, "Cancelled");
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
#include "../Oven.h"
|
#include "../OvenGUIApplication.h"
|
||||||
#include "OvenMainWindow.h"
|
|
||||||
|
|
||||||
#include "DomainBakeWidget.h"
|
#include "DomainBakeWidget.h"
|
||||||
|
|
||||||
|
@ -223,14 +222,14 @@ void DomainBakeWidget::bakeButtonClicked() {
|
||||||
connect(domainBaker.get(), &DomainBaker::bakeProgress, this, &DomainBakeWidget::handleBakerProgress);
|
connect(domainBaker.get(), &DomainBaker::bakeProgress, this, &DomainBakeWidget::handleBakerProgress);
|
||||||
|
|
||||||
// move the baker to the next available Oven worker thread
|
// move the baker to the next available Oven worker thread
|
||||||
auto nextThread = qApp->getNextWorkerThread();
|
auto nextThread = Oven::instance().getNextWorkerThread();
|
||||||
domainBaker->moveToThread(nextThread);
|
domainBaker->moveToThread(nextThread);
|
||||||
|
|
||||||
// kickoff the domain baker on its thread
|
// kickoff the domain baker on its thread
|
||||||
QMetaObject::invokeMethod(domainBaker.get(), "bake");
|
QMetaObject::invokeMethod(domainBaker.get(), "bake");
|
||||||
|
|
||||||
// add a pending row to the results window to show that this bake is in process
|
// 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 resultsRowName = _domainNameLineEdit->text().isEmpty() ? fileToBakeURL.fileName() : _domainNameLineEdit->text();
|
||||||
auto resultsRow = resultsWindow->addPendingResultRow(resultsRowName, outputDirectory);
|
auto resultsRow = resultsWindow->addPendingResultRow(resultsRowName, outputDirectory);
|
||||||
|
|
||||||
|
@ -250,7 +249,7 @@ void DomainBakeWidget::handleBakerProgress(int baked, int total) {
|
||||||
auto resultRow = it->second;
|
auto resultRow = it->second;
|
||||||
|
|
||||||
// grab the results window, don't force it to be brought to the top
|
// 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);
|
int percentage = roundf(float(baked) / float(total) * 100.0f);
|
||||||
|
|
||||||
|
@ -269,7 +268,7 @@ void DomainBakeWidget::handleFinishedBaker() {
|
||||||
|
|
||||||
if (it != _bakers.end()) {
|
if (it != _bakers.end()) {
|
||||||
auto resultRow = it->second;
|
auto resultRow = it->second;
|
||||||
auto resultsWindow = qApp->getMainWindow()->showResultsWindow();
|
auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow();
|
||||||
|
|
||||||
if (baker->hasErrors()) {
|
if (baker->hasErrors()) {
|
||||||
auto errors = baker->getErrors();
|
auto errors = baker->getErrors();
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include "../Oven.h"
|
#include "../OvenGUIApplication.h"
|
||||||
#include "OvenMainWindow.h"
|
|
||||||
|
|
||||||
#include "ModelBakeWidget.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
|
// everything seems to be in place, kick off a bake for this model now
|
||||||
auto baker = std::unique_ptr<FBXBaker> {
|
auto baker = std::unique_ptr<FBXBaker> {
|
||||||
new FBXBaker(modelToBakeURL, []() -> QThread* {
|
new FBXBaker(modelToBakeURL, []() -> QThread* {
|
||||||
return qApp->getNextWorkerThread();
|
return Oven::instance().getNextWorkerThread();
|
||||||
}, bakedOutputDirectory.absolutePath(), originalOutputDirectory.absolutePath())
|
}, bakedOutputDirectory.absolutePath(), originalOutputDirectory.absolutePath())
|
||||||
};
|
};
|
||||||
|
|
||||||
// move the baker to the FBX baker thread
|
// 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
|
// invoke the bake method on the baker thread
|
||||||
QMetaObject::invokeMethod(baker.get(), "bake");
|
QMetaObject::invokeMethod(baker.get(), "bake");
|
||||||
|
@ -222,7 +221,7 @@ void ModelBakeWidget::bakeButtonClicked() {
|
||||||
connect(baker.get(), &FBXBaker::finished, this, &ModelBakeWidget::handleFinishedBaker);
|
connect(baker.get(), &FBXBaker::finished, this, &ModelBakeWidget::handleFinishedBaker);
|
||||||
|
|
||||||
// add a pending row to the results window to show that this bake is in process
|
// 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);
|
auto resultsRow = resultsWindow->addPendingResultRow(modelToBakeURL.fileName(), outputDirectory);
|
||||||
|
|
||||||
// keep a unique_ptr to this baker
|
// keep a unique_ptr to this baker
|
||||||
|
@ -244,7 +243,7 @@ void ModelBakeWidget::handleFinishedBaker() {
|
||||||
|
|
||||||
if (it != _bakers.end()) {
|
if (it != _bakers.end()) {
|
||||||
auto resultRow = it->second;
|
auto resultRow = it->second;
|
||||||
auto resultsWindow = qApp->getMainWindow()->showResultsWindow();
|
auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow();
|
||||||
|
|
||||||
if (baker->hasErrors()) {
|
if (baker->hasErrors()) {
|
||||||
resultsWindow->changeStatusForRow(resultRow, baker->getErrors().join("\n"));
|
resultsWindow->changeStatusForRow(resultRow, baker->getErrors().join("\n"));
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include "../Oven.h"
|
#include "../OvenGUIApplication.h"
|
||||||
#include "OvenMainWindow.h"
|
|
||||||
|
|
||||||
#include "SkyboxBakeWidget.h"
|
#include "SkyboxBakeWidget.h"
|
||||||
|
|
||||||
|
@ -184,7 +183,7 @@ void SkyboxBakeWidget::bakeButtonClicked() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// move the baker to a worker thread
|
// move the baker to a worker thread
|
||||||
baker->moveToThread(qApp->getNextWorkerThread());
|
baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
|
|
||||||
// invoke the bake method on the baker thread
|
// invoke the bake method on the baker thread
|
||||||
QMetaObject::invokeMethod(baker.get(), "bake");
|
QMetaObject::invokeMethod(baker.get(), "bake");
|
||||||
|
@ -193,7 +192,7 @@ void SkyboxBakeWidget::bakeButtonClicked() {
|
||||||
connect(baker.get(), &TextureBaker::finished, this, &SkyboxBakeWidget::handleFinishedBaker);
|
connect(baker.get(), &TextureBaker::finished, this, &SkyboxBakeWidget::handleFinishedBaker);
|
||||||
|
|
||||||
// add a pending row to the results window to show that this bake is in process
|
// 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);
|
auto resultsRow = resultsWindow->addPendingResultRow(skyboxToBakeURL.fileName(), outputDirectory);
|
||||||
|
|
||||||
// keep a unique_ptr to this baker
|
// keep a unique_ptr to this baker
|
||||||
|
@ -211,7 +210,7 @@ void SkyboxBakeWidget::handleFinishedBaker() {
|
||||||
|
|
||||||
if (it != _bakers.end()) {
|
if (it != _bakers.end()) {
|
||||||
auto resultRow = it->second;
|
auto resultRow = it->second;
|
||||||
auto resultsWindow = qApp->getMainWindow()->showResultsWindow();
|
auto resultsWindow = OvenGUIApplication::instance()->getMainWindow()->showResultsWindow();
|
||||||
|
|
||||||
if (baker->hasErrors()) {
|
if (baker->hasErrors()) {
|
||||||
resultsWindow->changeStatusForRow(resultRow, baker->getErrors().join("\n"));
|
resultsWindow->changeStatusForRow(resultRow, baker->getErrors().join("\n"));
|
||||||
|
|
Loading…
Reference in a new issue