mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-16 21:47:09 +02:00
CR feedback; remove ok bool pointer and all metadata; cleanup
This commit is contained in:
parent
0dd3672162
commit
6ea4b660b7
29 changed files with 307 additions and 575 deletions
|
@ -36,7 +36,7 @@ public:
|
|||
virtual bool is3D() const override { return true; }
|
||||
|
||||
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); }
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override { return scriptable::ModelProvider::modelUnavailableError(ok); }
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
|
||||
|
||||
// TODO: consider implementing registration points in this class
|
||||
glm::vec3 getCenter() const { return getWorldPosition(); }
|
||||
|
|
|
@ -665,11 +665,11 @@ void ModelOverlay::processMaterials() {
|
|||
}
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase ModelOverlay::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() {
|
||||
if (!_model || !_model->isLoaded()) {
|
||||
return Base3DOverlay::getScriptableModel(ok);
|
||||
return Base3DOverlay::getScriptableModel();
|
||||
}
|
||||
auto result = _model->getScriptableModel(ok);
|
||||
auto result = _model->getScriptableModel();
|
||||
result.objectID = getID();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override;
|
||||
void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override;
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
|
|
|
@ -180,14 +180,13 @@ Transform Shape3DOverlay::evalRenderTransform() {
|
|||
return transform;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase Shape3DOverlay::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase Shape3DOverlay::getScriptableModel() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto vertexColor = ColorUtils::toVec3(_color);
|
||||
scriptable::ScriptableModelBase result;
|
||||
result.objectID = getID();
|
||||
result.append(geometryCache->meshFromShape(_shape, vertexColor), {{ "shape", shapeStrings[_shape] }});
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
if (auto mesh = geometryCache->meshFromShape(_shape, vertexColor)) {
|
||||
result.append(mesh);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
|
|
|
@ -1795,22 +1795,11 @@ void Avatar::processMaterials() {
|
|||
}
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase Avatar::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase Avatar::getScriptableModel() {
|
||||
if (!_skeletonModel || !_skeletonModel->isLoaded()) {
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
return scriptable::ScriptableModelBase();
|
||||
}
|
||||
scriptable::ScriptableModelBase result = _skeletonModel->getScriptableModel(ok);
|
||||
auto result = _skeletonModel->getScriptableModel();
|
||||
result.objectID = getSessionUUID();
|
||||
result.mixin({{ "textures", _skeletonModel->getTextures() }});
|
||||
// FIXME: for now access to attachment models are merged into the main avatar ScriptableModel set
|
||||
for (int i = 0; i < (int)_attachmentModels.size(); i++) {
|
||||
auto& model = _attachmentModels.at(i);
|
||||
if (model->isLoaded()) {
|
||||
result.append(model->getScriptableModel(ok), _attachmentData.at(i).toVariant().toMap());
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -276,7 +276,7 @@ public:
|
|||
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override;
|
||||
void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override;
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
|
||||
public slots:
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
|
||||
virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override { return scriptable::ModelProvider::modelUnavailableError(ok); }
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
|
||||
|
||||
protected:
|
||||
virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); }
|
||||
|
|
|
@ -960,15 +960,15 @@ bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) {
|
|||
return !result.isEmpty();
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
||||
ModelPointer model;
|
||||
withReadLock([&] { model = _model; });
|
||||
|
||||
if (!model || !model->isLoaded()) {
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
return scriptable::ScriptableModelBase();
|
||||
}
|
||||
|
||||
auto result = _model->getScriptableModel(ok);
|
||||
auto result = _model->getScriptableModel();
|
||||
result.objectID = getEntity()->getID();
|
||||
return result;
|
||||
}
|
||||
|
@ -981,7 +981,7 @@ bool render::entities::ModelEntityRenderer::replaceScriptableModelMeshPart(scrip
|
|||
return false;
|
||||
}
|
||||
|
||||
return model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
||||
return model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::simulateRelayedJoints() {
|
||||
|
|
|
@ -142,7 +142,7 @@ class ModelEntityRenderer : public TypedEntityRenderer<RenderableModelEntityItem
|
|||
|
||||
public:
|
||||
ModelEntityRenderer(const EntityItemPointer& entity);
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override;
|
||||
|
||||
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override;
|
||||
|
|
|
@ -281,9 +281,9 @@ std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertic
|
|||
return vertices;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase PolyLineEntityRenderer::getScriptableModel(bool *ok) {
|
||||
scriptable::ScriptableModelBase PolyLineEntityRenderer::getScriptableModel() {
|
||||
// TODO: adapt polyline into a triangles mesh...
|
||||
return EntityRenderer::getScriptableModel(ok);
|
||||
return EntityRenderer::getScriptableModel();
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
||||
|
|
|
@ -25,7 +25,7 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
|||
public:
|
||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene,
|
||||
|
|
|
@ -1451,9 +1451,9 @@ bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {
|
|||
return success;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase RenderablePolyVoxEntityItem::getScriptableModel(bool * ok) {
|
||||
scriptable::ScriptableModelBase RenderablePolyVoxEntityItem::getScriptableModel() {
|
||||
if (!updateDependents() || !_mesh) {
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
return scriptable::ScriptableModelBase();
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
@ -1479,9 +1479,6 @@ scriptable::ScriptableModelBase RenderablePolyVoxEntityItem::getScriptableModel(
|
|||
));
|
||||
}
|
||||
});
|
||||
if (ok) {
|
||||
*ok = success;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
|
||||
|
||||
bool getMeshes(MeshProxyList& result) override; // deprecated
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
|
||||
private:
|
||||
bool updateOnCount(const ivec3& v, uint8_t toValue);
|
||||
|
@ -164,8 +164,8 @@ class PolyVoxEntityRenderer : public TypedEntityRenderer<RenderablePolyVoxEntity
|
|||
|
||||
public:
|
||||
PolyVoxEntityRenderer(const EntityItemPointer& entity);
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override {
|
||||
return asTypedEntity<RenderablePolyVoxEntityItem>()->getScriptableModel(ok);
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override {
|
||||
return asTypedEntity<RenderablePolyVoxEntityItem>()->getScriptableModel();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -164,22 +164,17 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel() {
|
||||
scriptable::ScriptableModelBase result;
|
||||
result.objectID = getEntity()->getID();
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
glm::vec3 vertexColor;
|
||||
if (_materials["0"].top().material) {
|
||||
vertexColor = _materials["0"].top().material->getAlbedo();
|
||||
}
|
||||
auto success = false;
|
||||
if (auto mesh = geometryCache->meshFromShape(geometryShape, vertexColor)) {
|
||||
result.append({ mesh, {{ "shape", entity::stringFromShape(_shape) }}});
|
||||
success = true;
|
||||
}
|
||||
if (ok) {
|
||||
*ok = success;
|
||||
result.objectID = getEntity()->getID();
|
||||
result.append(mesh);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ class ShapeEntityRenderer : public TypedEntityRenderer<ShapeEntityItem> {
|
|||
public:
|
||||
ShapeEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
|
|
|
@ -36,16 +36,14 @@ namespace scriptable {
|
|||
public:
|
||||
WeakModelProviderPointer provider;
|
||||
ScriptableModelBasePointer model;
|
||||
WeakMeshPointer mesh;
|
||||
MeshPointer ownedMesh;
|
||||
QVariantMap metadata;
|
||||
ScriptableMeshBase(WeakModelProviderPointer provider, ScriptableModelBasePointer model, WeakMeshPointer mesh, const QVariantMap& metadata);
|
||||
ScriptableMeshBase(WeakMeshPointer mesh = WeakMeshPointer());
|
||||
ScriptableMeshBase(MeshPointer mesh, const QVariantMap& metadata);
|
||||
ScriptableMeshBase(const ScriptableMeshBase& other) : QObject() { *this = other; }
|
||||
WeakMeshPointer weakMesh;
|
||||
MeshPointer strongMesh;
|
||||
ScriptableMeshBase(WeakModelProviderPointer provider, ScriptableModelBasePointer model, WeakMeshPointer weakMesh, QObject* parent);
|
||||
ScriptableMeshBase(WeakMeshPointer weakMesh = WeakMeshPointer(), QObject* parent = nullptr);
|
||||
ScriptableMeshBase(const ScriptableMeshBase& other, QObject* parent = nullptr) : QObject(parent) { *this = other; }
|
||||
ScriptableMeshBase& operator=(const ScriptableMeshBase& view);
|
||||
virtual ~ScriptableMeshBase();
|
||||
Q_INVOKABLE const scriptable::MeshPointer getMeshPointer() const { return mesh.lock(); }
|
||||
Q_INVOKABLE const scriptable::MeshPointer getMeshPointer() const { return weakMesh.lock(); }
|
||||
Q_INVOKABLE const scriptable::ModelProviderPointer getModelProviderPointer() const { return provider.lock(); }
|
||||
Q_INVOKABLE const scriptable::ScriptableModelBasePointer getModelBasePointer() const { return model; }
|
||||
};
|
||||
|
@ -56,18 +54,15 @@ namespace scriptable {
|
|||
public:
|
||||
WeakModelProviderPointer provider;
|
||||
QUuid objectID; // spatially nestable ID
|
||||
QVariantMap metadata;
|
||||
QVector<scriptable::ScriptableMeshBase> meshes;
|
||||
|
||||
ScriptableModelBase(QObject* parent = nullptr) : QObject(parent) {}
|
||||
ScriptableModelBase(const ScriptableModelBase& other) : QObject() { *this = other; }
|
||||
ScriptableModelBase(const ScriptableModelBase& other) : QObject(other.parent()) { *this = other; }
|
||||
ScriptableModelBase& operator=(const ScriptableModelBase& other);
|
||||
virtual ~ScriptableModelBase();
|
||||
|
||||
void mixin(const QVariantMap& other);
|
||||
void append(const ScriptableModelBase& other, const QVariantMap& modelMetadata = QVariantMap());
|
||||
void append(scriptable::WeakMeshPointer mesh, const QVariantMap& metadata = QVariantMap());
|
||||
void append(const ScriptableMeshBase& mesh, const QVariantMap& metadata = QVariantMap());
|
||||
void append(const ScriptableMeshBase& mesh);
|
||||
void append(scriptable::WeakMeshPointer mesh);
|
||||
// TODO: in future containers for these could go here
|
||||
// QVariantMap shapes;
|
||||
// QVariantMap materials;
|
||||
|
@ -78,8 +73,7 @@ namespace scriptable {
|
|||
class ModelProvider {
|
||||
public:
|
||||
NestableType modelProviderType;
|
||||
static scriptable::ScriptableModelBase modelUnavailableError(bool* ok) { if (ok) { *ok = false; } return {}; }
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) = 0;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() = 0;
|
||||
|
||||
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) { return false; }
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//
|
||||
|
||||
#include "GraphicsScriptingInterface.h"
|
||||
#include "BaseScriptEngine.h"
|
||||
#include "BufferViewScripting.h"
|
||||
#include "GraphicsScriptingUtil.h"
|
||||
#include "OBJWriter.h"
|
||||
|
@ -24,86 +23,119 @@
|
|||
#include <graphics/BufferViewHelpers.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include "GraphicsScriptingInterface.moc"
|
||||
|
||||
GraphicsScriptingInterface::GraphicsScriptingInterface(QObject* parent) : QObject(parent), QScriptable() {
|
||||
if (auto scriptEngine = qobject_cast<QScriptEngine*>(parent)) {
|
||||
this->registerMetaTypes(scriptEngine);
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsScriptingInterface::updateMeshes(QUuid uuid, const scriptable::ScriptableMeshPointer mesh, int meshIndex, int partIndex) {
|
||||
auto model = scriptable::make_qtowned<scriptable::ScriptableModel>();
|
||||
if (mesh) {
|
||||
model->append(*mesh);
|
||||
}
|
||||
return updateMeshes(uuid, model.get());
|
||||
}
|
||||
|
||||
bool GraphicsScriptingInterface::updateMeshes(QUuid uuid, const scriptable::ScriptableModelPointer model) {
|
||||
auto appProvider = DependencyManager::get<scriptable::ModelProviderFactory>();
|
||||
scriptable::ModelProviderPointer provider = appProvider ? appProvider->lookupModelProvider(uuid) : nullptr;
|
||||
QString providerType = provider ? SpatiallyNestable::nestableTypeToString(provider->modelProviderType) : QString();
|
||||
if (providerType.isEmpty()) {
|
||||
providerType = "unknown";
|
||||
}
|
||||
bool success = false;
|
||||
if (provider) {
|
||||
auto scriptableMeshes = provider->getScriptableModel(&success);
|
||||
if (success) {
|
||||
const scriptable::ScriptableModelBasePointer base = model->operator scriptable::ScriptableModelBasePointer();
|
||||
if (base) {
|
||||
success = provider->replaceScriptableModelMeshPart(base, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
QScriptValue GraphicsScriptingInterface::getMeshes(QUuid uuid) {
|
||||
scriptable::ScriptableModel* meshes{ nullptr };
|
||||
bool success = false;
|
||||
QString error;
|
||||
|
||||
auto appProvider = DependencyManager::get<scriptable::ModelProviderFactory>();
|
||||
qCDebug(graphics_scripting) << "appProvider" << appProvider.data();
|
||||
scriptable::ModelProviderPointer provider = appProvider ? appProvider->lookupModelProvider(uuid) : nullptr;
|
||||
QString providerType = provider ? SpatiallyNestable::nestableTypeToString(provider->modelProviderType) : QString();
|
||||
if (providerType.isEmpty()) {
|
||||
providerType = "unknown";
|
||||
}
|
||||
if (provider) {
|
||||
auto scriptableMeshes = provider->getScriptableModel(&success);
|
||||
if (success) {
|
||||
meshes = scriptable::make_scriptowned<scriptable::ScriptableModel>(scriptableMeshes);
|
||||
if (meshes->objectName().isEmpty()) {
|
||||
meshes->setObjectName(providerType+"::meshes");
|
||||
}
|
||||
if (meshes->objectID.isNull()) {
|
||||
meshes->objectID = uuid.toString();
|
||||
}
|
||||
meshes->metadata["provider"] = SpatiallyNestable::nestableTypeToString(provider->modelProviderType);
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
error = QString("failed to get meshes from %1 provider for uuid %2").arg(providerType).arg(uuid.toString());
|
||||
}
|
||||
|
||||
QPointer<BaseScriptEngine> scriptEngine = dynamic_cast<BaseScriptEngine*>(engine());
|
||||
QScriptValue result = error.isEmpty() ? scriptEngine->toScriptValue(meshes) : scriptEngine->makeError(error);
|
||||
if (result.isError()) {
|
||||
qCWarning(graphics_scripting) << "GraphicsScriptingInterface::getMeshes ERROR" << result.toString();
|
||||
if (context()) {
|
||||
context()->throwValue(error);
|
||||
bool GraphicsScriptingInterface::updateModelObject(QUuid uuid, const scriptable::ScriptableModelPointer model) {
|
||||
if (auto provider = getModelProvider(uuid)) {
|
||||
if (auto base = model->operator scriptable::ScriptableModelBasePointer()) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qDebug() << "replaceScriptableModelMeshPart" << model->toString() << -1 << -1;
|
||||
#endif
|
||||
return provider->replaceScriptableModelMeshPart(base, -1, -1);
|
||||
} else {
|
||||
qCWarning(graphics_scripting) << "GraphicsScriptingInterface::getMeshes ERROR" << result.toString();
|
||||
qDebug() << "replaceScriptableModelMeshPart -- !base" << model << base << -1 << -1;
|
||||
}
|
||||
return QScriptValue::NullValue;
|
||||
} else {
|
||||
qDebug() << "replaceScriptableModelMeshPart -- !provider";
|
||||
}
|
||||
return scriptEngine->toScriptValue(meshes);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString GraphicsScriptingInterface::meshToOBJ(const scriptable::ScriptableModel& _in) {
|
||||
scriptable::ModelProviderPointer GraphicsScriptingInterface::getModelProvider(QUuid uuid) {
|
||||
QString error;
|
||||
if (auto appProvider = DependencyManager::get<scriptable::ModelProviderFactory>()) {
|
||||
if (auto provider = appProvider->lookupModelProvider(uuid)) {
|
||||
return provider;
|
||||
} else {
|
||||
error = "provider unavailable for " + uuid.toString();
|
||||
}
|
||||
} else {
|
||||
error = "appProvider unavailable";
|
||||
}
|
||||
if (context()) {
|
||||
context()->throwError(error);
|
||||
} else {
|
||||
qCWarning(graphics_scripting) << "GraphicsScriptingInterface::getModelProvider ERROR" << error;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelPointer GraphicsScriptingInterface::newModelObject(QVector<scriptable::ScriptableMeshPointer> meshes) {
|
||||
auto modelWrapper = scriptable::make_scriptowned<scriptable::ScriptableModel>();
|
||||
modelWrapper->setObjectName("js::model");
|
||||
if (meshes.isEmpty()) {
|
||||
if (context()) {
|
||||
context()->throwError("expected [meshes] array as first argument");
|
||||
}
|
||||
} else {
|
||||
int i = 0;
|
||||
for (const auto& mesh : meshes) {
|
||||
if (mesh) {
|
||||
modelWrapper->append(*mesh);
|
||||
} else if (context()) {
|
||||
context()->throwError(QString("invalid mesh at index: %1").arg(i));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return modelWrapper;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelPointer GraphicsScriptingInterface::getModelObject(QUuid uuid) {
|
||||
QString error, providerType = "unknown";
|
||||
if (auto provider = getModelProvider(uuid)) {
|
||||
providerType = SpatiallyNestable::nestableTypeToString(provider->modelProviderType);
|
||||
auto modelObject = provider->getScriptableModel();
|
||||
if (modelObject.objectID == uuid) {
|
||||
if (modelObject.meshes.size()) {
|
||||
auto modelWrapper = scriptable::make_scriptowned<scriptable::ScriptableModel>(modelObject);
|
||||
modelWrapper->setObjectName(providerType+"::"+uuid.toString()+"::model");
|
||||
return modelWrapper;
|
||||
} else {
|
||||
error = "no meshes available: " + modelObject.objectID.toString();
|
||||
}
|
||||
} else {
|
||||
error = "objectID mismatch: " + modelObject.objectID.toString();
|
||||
}
|
||||
} else {
|
||||
error = "provider unavailable";
|
||||
}
|
||||
auto errorMessage = QString("failed to get meshes from %1 provider for uuid %2 (%3)").arg(providerType).arg(uuid.toString()).arg(error);
|
||||
qCWarning(graphics_scripting) << "GraphicsScriptingInterface::getModelObject ERROR" << errorMessage;
|
||||
if (context()) {
|
||||
context()->throwError(errorMessage);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef SCRIPTABLE_MESH_TODO
|
||||
bool GraphicsScriptingInterface::updateMeshPart(scriptable::ScriptableMeshPointer mesh, scriptable::ScriptableMeshPartPointer part) {
|
||||
Q_ASSERT(mesh);
|
||||
Q_ASSERT(part);
|
||||
Q_ASSERT(part->parentMesh);
|
||||
auto tmp = exportMeshPart(mesh, part->partIndex);
|
||||
if (part->parentMesh == mesh) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "updateMeshPart -- update via clone" << mesh << part;
|
||||
#endif
|
||||
tmp->replaceMeshData(part->cloneMeshPart());
|
||||
return false;
|
||||
} else {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "updateMeshPart -- update via inplace" << mesh << part;
|
||||
#endif
|
||||
tmp->replaceMeshData(part);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QString GraphicsScriptingInterface::exportModelToOBJ(const scriptable::ScriptableModel& _in) {
|
||||
const auto& in = _in.getConstMeshes();
|
||||
if (in.size()) {
|
||||
QList<scriptable::MeshPointer> meshes;
|
||||
|
@ -152,3 +184,5 @@ MeshPointer GraphicsScriptingInterface::getMeshPointer(scriptable::ScriptableMes
|
|||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
#include "GraphicsScriptingInterface.moc"
|
||||
|
|
|
@ -29,16 +29,24 @@ public:
|
|||
|
||||
public slots:
|
||||
/**jsdoc
|
||||
* Returns the meshes associated with a UUID (entityID, overlayID, or avatarID)
|
||||
* Returns the model/meshes associated with a UUID (entityID, overlayID, or avatarID)
|
||||
*
|
||||
* @function GraphicsScriptingInterface.getMeshes
|
||||
* @param {EntityID} entityID The ID of the entity whose meshes are to be retrieve
|
||||
* @function GraphicsScriptingInterface.getModel
|
||||
* @param {UUID} The objectID of the model whose meshes are to be retrieve
|
||||
*/
|
||||
QScriptValue getMeshes(QUuid uuid);
|
||||
bool updateMeshes(QUuid uuid, const scriptable::ScriptableModelPointer model);
|
||||
bool updateMeshes(QUuid uuid, const scriptable::ScriptableMeshPointer mesh, int meshIndex=0, int partIndex=0);
|
||||
scriptable::ModelProviderPointer getModelProvider(QUuid uuid);
|
||||
scriptable::ScriptableModelPointer getModelObject(QUuid uuid);
|
||||
bool updateModelObject(QUuid uuid, const scriptable::ScriptableModelPointer model);
|
||||
scriptable::ScriptableModelPointer newModelObject(QVector<scriptable::ScriptableMeshPointer> meshes);
|
||||
|
||||
QString meshToOBJ(const scriptable::ScriptableModel& in);
|
||||
#ifdef SCRIPTABLE_MESH_TODO
|
||||
scriptable::ScriptableMeshPartPointer exportMeshPart(scriptable::ScriptableMeshPointer mesh, int part=0) {
|
||||
return scriptable::make_scriptowned<scriptable::ScriptableMeshPart>(mesh, part);
|
||||
}
|
||||
bool updateMeshPart(scriptable::ScriptableMeshPointer mesh, scriptable::ScriptableMeshPartPointer part);
|
||||
#endif
|
||||
|
||||
QString exportModelToOBJ(const scriptable::ScriptableModel& in);
|
||||
|
||||
private:
|
||||
scriptable::MeshPointer getMeshPointer(scriptable::ScriptableMeshPointer meshProxy);
|
||||
|
|
|
@ -43,23 +43,13 @@ namespace scriptable {
|
|||
return toDebugString(qobject_cast<QObject*>(tmp.get()));
|
||||
}
|
||||
|
||||
// C++ > QtOwned instance
|
||||
template <typename T, class... Rest>
|
||||
std::shared_ptr<T> make_qtowned(Rest... rest) {
|
||||
T* tmp = new T(rest...);
|
||||
if (tmp) {
|
||||
tmp->metadata["__ownership__"] = QScriptEngine::QtOwnership;
|
||||
}
|
||||
return std::shared_ptr<T>(tmp);
|
||||
}
|
||||
|
||||
// C++ > ScriptOwned JS instance
|
||||
// Helper for creating C++ > ScriptOwned JS instances
|
||||
// (NOTE: this also helps track in the code where we need to update later if switching to
|
||||
// std::shared_ptr's -- something currently non-trivial given mixed JS/C++ object ownership)
|
||||
template <typename T, class... Rest>
|
||||
QPointer<T> make_scriptowned(Rest... rest) {
|
||||
T* tmp = new T(rest...);
|
||||
if (tmp) {
|
||||
tmp->metadata["__ownership__"] = QScriptEngine::ScriptOwnership;
|
||||
}
|
||||
return QPointer<T>(tmp);
|
||||
auto instance = QPointer<T>(new T(rest...));
|
||||
Q_ASSERT(instance && instance->parent());
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include "ScriptableMesh.h"
|
||||
|
||||
#include "BufferViewScripting.h"
|
||||
|
@ -19,7 +21,7 @@
|
|||
#include <graphics/BufferViewHelpers.h>
|
||||
#include <graphics/Geometry.h>
|
||||
|
||||
#include "ScriptableMesh.moc"
|
||||
// #define SCRIPTABLE_MESH_DEBUG 1
|
||||
|
||||
scriptable::ScriptableMeshPart::ScriptableMeshPart(scriptable::ScriptableMeshPointer parentMesh, int partIndex)
|
||||
: QObject(), parentMesh(parentMesh), partIndex(partIndex) {
|
||||
|
@ -77,7 +79,9 @@ QVector<quint32> scriptable::ScriptableMesh::findNearbyIndices(const glm::vec3&
|
|||
QVector<quint32> scriptable::ScriptableMesh::getIndices() const {
|
||||
QVector<quint32> result;
|
||||
if (auto mesh = getMeshPointer()) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCDebug(graphics_scripting, "getTriangleIndices mesh %p", mesh.get());
|
||||
#endif
|
||||
gpu::BufferView indexBufferView = mesh->getIndexBuffer();
|
||||
if (quint32 count = (quint32)indexBufferView.getNumElements()) {
|
||||
result.resize(count);
|
||||
|
@ -121,20 +125,16 @@ QVector<QString> scriptable::ScriptableMesh::getAttributeNames() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
// override
|
||||
QVariantMap scriptable::ScriptableMesh::getVertexAttributes(quint32 vertexIndex) const {
|
||||
return getVertexAttributes(vertexIndex, getAttributeNames());
|
||||
}
|
||||
|
||||
bool scriptable::ScriptableMesh::setVertexAttributes(quint32 vertexIndex, QVariantMap attributes) {
|
||||
//qCInfo(graphics_scripting) << "setVertexAttributes" << vertexIndex << attributes;
|
||||
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||
for (auto& a : buffer_helpers::gatherBufferViews(getMeshPointer())) {
|
||||
const auto& name = a.first;
|
||||
const auto& value = attributes.value(name);
|
||||
if (value.isValid()) {
|
||||
auto& view = a.second;
|
||||
//qCDebug(graphics_scripting) << "setVertexAttributes" << vertexIndex << name;
|
||||
buffer_helpers::fromVariant(view, vertexIndex, value);
|
||||
} else {
|
||||
//qCDebug(graphics_scripting) << "(skipping) setVertexAttributes" << vertexIndex << name;
|
||||
|
@ -269,7 +269,6 @@ quint32 scriptable::ScriptableMesh::mapAttributeValues(QScriptValue _callback) {
|
|||
#endif
|
||||
auto obj = js->newObject();
|
||||
auto attributeViews = buffer_helpers::gatherBufferViews(mesh, { "normal", "color" });
|
||||
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||
uint32_t i = 0;
|
||||
for (; i < nPositions; i++) {
|
||||
for (const auto& a : attributeViews) {
|
||||
|
@ -303,13 +302,13 @@ quint32 scriptable::ScriptableMesh::mapAttributeValues(QScriptValue _callback) {
|
|||
}
|
||||
|
||||
quint32 scriptable::ScriptableMeshPart::mapAttributeValues(QScriptValue callback) {
|
||||
return parentMesh ? parentMesh->mapAttributeValues(callback) : 0;
|
||||
return parentMesh ? parentMesh->mapAttributeValues(callback) : 0;
|
||||
}
|
||||
|
||||
bool scriptable::ScriptableMeshPart::unrollVertices(bool recalcNormals) {
|
||||
auto mesh = getMeshPointer();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices" << !!mesh<< !!meshProxy;
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices" << !!mesh<< !!parentMesh;
|
||||
#endif
|
||||
if (!mesh) {
|
||||
return false;
|
||||
|
@ -321,8 +320,9 @@ bool scriptable::ScriptableMeshPart::unrollVertices(bool recalcNormals) {
|
|||
auto buffer = new gpu::Buffer();
|
||||
buffer->resize(numPoints * sizeof(uint32_t));
|
||||
auto newindices = gpu::BufferView(buffer, { gpu::SCALAR, gpu::UINT32, gpu::INDEX });
|
||||
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices numPoints" << numPoints;
|
||||
#endif
|
||||
auto attributeViews = buffer_helpers::gatherBufferViews(mesh);
|
||||
for (const auto& a : attributeViews) {
|
||||
auto& view = a.second;
|
||||
|
@ -330,15 +330,17 @@ bool scriptable::ScriptableMeshPart::unrollVertices(bool recalcNormals) {
|
|||
auto buffer = new gpu::Buffer();
|
||||
buffer->resize(numPoints * sz);
|
||||
auto points = gpu::BufferView(buffer, view._element);
|
||||
auto src = (uint8_t*)view._buffer->getData();
|
||||
auto dest = (uint8_t*)points._buffer->getData();
|
||||
auto slot = buffer_helpers::ATTRIBUTES[a.first];
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
if (0) {
|
||||
auto src = (uint8_t*)view._buffer->getData();
|
||||
auto dest = (uint8_t*)points._buffer->getData();
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices buffer" << a.first;
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices source" << view.getNumElements();
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices dest" << points.getNumElements();
|
||||
qCInfo(graphics_scripting) << "ScriptableMeshPart::unrollVertices sz" << sz << src << dest << slot;
|
||||
}
|
||||
#endif
|
||||
auto esize = indices._element.getSize();
|
||||
const char* hint= a.first.toStdString().c_str();
|
||||
for(quint32 i = 0; i < numPoints; i++) {
|
||||
|
@ -381,8 +383,6 @@ bool scriptable::ScriptableMeshPart::replaceMeshData(scriptable::ScriptableMeshP
|
|||
"target:" << QString::fromStdString(target->displayName) <<
|
||||
"attributes:" << attributes;
|
||||
|
||||
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||
|
||||
// remove attributes only found on target mesh, unless user has explicitly specified the relevant attribute names
|
||||
if (attributeNames.isEmpty()) {
|
||||
auto attributeViews = buffer_helpers::gatherBufferViews(target);
|
||||
|
@ -438,7 +438,6 @@ bool scriptable::ScriptableMeshPart::dedupeVertices(float epsilon) {
|
|||
uniqueVerts.reserve((int)numPositions);
|
||||
QMap<quint32,quint32> remapIndices;
|
||||
|
||||
metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||
for (quint32 i = 0; i < numPositions; i++) {
|
||||
const quint32 numUnique = uniqueVerts.size();
|
||||
const auto& position = positions.get<glm::vec3>(i);
|
||||
|
@ -508,63 +507,51 @@ scriptable::ScriptableMeshPointer scriptable::ScriptableMesh::cloneMesh(bool rec
|
|||
return nullptr;
|
||||
}
|
||||
auto clone = buffer_helpers::cloneMesh(mesh);
|
||||
|
||||
|
||||
if (recalcNormals) {
|
||||
buffer_helpers::recalculateNormals(clone);
|
||||
}
|
||||
auto meshPointer = scriptable::make_scriptowned<scriptable::ScriptableMesh>(provider, model, clone, metadata);
|
||||
clone.reset(); // free local reference
|
||||
// qCInfo(graphics_scripting) << "========= ScriptableMesh::cloneMesh..." << meshPointer << meshPointer->ownedMesh.use_count();
|
||||
//scriptable::MeshPointer* ppMesh = new scriptable::MeshPointer();
|
||||
//*ppMesh = clone;
|
||||
|
||||
if (0 && meshPointer) {
|
||||
scriptable::WeakMeshPointer delme = meshPointer->mesh;
|
||||
QString debugString = scriptable::toDebugString(meshPointer);
|
||||
QObject::connect(meshPointer, &QObject::destroyed, meshPointer, [=]() {
|
||||
// qCWarning(graphics_scripting) << "*************** cloneMesh/Destroy";
|
||||
// qCWarning(graphics_scripting) << "*************** " << debugString << delme.lock().get();
|
||||
if (!delme.expired()) {
|
||||
QTimer::singleShot(250, this, [=]{
|
||||
if (!delme.expired()) {
|
||||
qCWarning(graphics_scripting) << "cloneMesh -- potential memory leak..." << debugString << delme.use_count();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
meshPointer->metadata["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate);
|
||||
auto meshPointer = scriptable::make_scriptowned<scriptable::ScriptableMesh>(provider, model, clone, nullptr);
|
||||
return scriptable::ScriptableMeshPointer(meshPointer);
|
||||
}
|
||||
|
||||
scriptable::ScriptableMeshBase::ScriptableMeshBase(scriptable::WeakModelProviderPointer provider, scriptable::ScriptableModelBasePointer model, scriptable::WeakMeshPointer mesh, const QVariantMap& metadata)
|
||||
: provider(provider), model(model), mesh(mesh), metadata(metadata) {}
|
||||
scriptable::ScriptableMeshBase::ScriptableMeshBase(scriptable::WeakMeshPointer mesh) : scriptable::ScriptableMeshBase(scriptable::WeakModelProviderPointer(), nullptr, mesh, QVariantMap()) { }
|
||||
scriptable::ScriptableMeshBase::ScriptableMeshBase(scriptable::MeshPointer mesh, const QVariantMap& metadata)
|
||||
: ScriptableMeshBase(WeakModelProviderPointer(), nullptr, mesh, metadata) {
|
||||
ownedMesh = mesh;
|
||||
|
||||
|
||||
// note: we don't always want the JS side to prevent mesh data from being freed
|
||||
|
||||
scriptable::ScriptableMeshBase::ScriptableMeshBase(
|
||||
scriptable::WeakModelProviderPointer provider, scriptable::ScriptableModelBasePointer model, scriptable::WeakMeshPointer weakMesh, QObject* parent
|
||||
) : QObject(parent), provider(provider), model(model), weakMesh(weakMesh) {
|
||||
if (parent) {
|
||||
qCDebug(graphics_scripting) << "ScriptableMeshBase -- have parent QObject, creating strong neshref" << weakMesh.lock().get() << parent;
|
||||
strongMesh = weakMesh.lock();
|
||||
}
|
||||
}
|
||||
|
||||
scriptable::ScriptableMeshBase::ScriptableMeshBase(scriptable::WeakMeshPointer weakMesh, QObject* parent) :
|
||||
scriptable::ScriptableMeshBase(scriptable::WeakModelProviderPointer(), nullptr, weakMesh, parent) {
|
||||
}
|
||||
|
||||
scriptable::ScriptableMeshBase& scriptable::ScriptableMeshBase::operator=(const scriptable::ScriptableMeshBase& view) {
|
||||
provider = view.provider;
|
||||
model = view.model;
|
||||
mesh = view.mesh;
|
||||
ownedMesh = view.ownedMesh;
|
||||
metadata = view.metadata;
|
||||
weakMesh = view.weakMesh;
|
||||
strongMesh = view.strongMesh;
|
||||
return *this;
|
||||
}
|
||||
scriptable::ScriptableMeshBase::~ScriptableMeshBase() {
|
||||
ownedMesh.reset();
|
||||
|
||||
scriptable::ScriptableMeshBase::~ScriptableMeshBase() {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "//~ScriptableMeshBase" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
||||
qCInfo(graphics_scripting) << "//~ScriptableMeshBase" << this << "strongMesh:" << strongMesh.use_count() << "weakMesh:" << weakMesh.use_count();
|
||||
#endif
|
||||
strongMesh.reset();
|
||||
}
|
||||
|
||||
scriptable::ScriptableMesh::~ScriptableMesh() {
|
||||
ownedMesh.reset();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "//~ScriptableMesh" << this << "ownedMesh:" << ownedMesh.use_count() << "mesh:" << mesh.use_count();
|
||||
qCInfo(graphics_scripting) << "//~ScriptableMesh" << this << "strongMesh:" << strongMesh.use_count() << "weakMesh:" << weakMesh.use_count();
|
||||
#endif
|
||||
strongMesh.reset();
|
||||
}
|
||||
|
||||
QString scriptable::ScriptableMeshPart::toOBJ() {
|
||||
|
@ -573,7 +560,7 @@ QString scriptable::ScriptableMeshPart::toOBJ() {
|
|||
context()->throwError(QString("null mesh"));
|
||||
} else {
|
||||
qCWarning(graphics_scripting) << "null mesh";
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
return writeOBJToString({ getMeshPointer() });
|
||||
|
@ -585,12 +572,7 @@ namespace {
|
|||
if (!object) {
|
||||
return QScriptValue::NullValue;
|
||||
}
|
||||
auto ownership = object->metadata.value("__ownership__");
|
||||
return engine->newQObject(
|
||||
object,
|
||||
ownership.isValid() ? static_cast<QScriptEngine::ValueOwnership>(ownership.toInt()) : QScriptEngine::QtOwnership
|
||||
//, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects
|
||||
);
|
||||
return engine->newQObject(object, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater);
|
||||
}
|
||||
|
||||
QScriptValue meshPointerToScriptValue(QScriptEngine* engine, const scriptable::ScriptableMeshPointer& in) {
|
||||
|
@ -637,7 +619,7 @@ namespace scriptable {
|
|||
qScriptRegisterSequenceMetaType<QVector<scriptable::ScriptableMeshPartPointer>>(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<scriptable::ScriptableMeshPointer>>(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<scriptable::uint32>>(engine);
|
||||
|
||||
|
||||
qScriptRegisterMetaType(engine, qVectorUInt32ToScriptValue, qVectorUInt32FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, modelPointerToScriptValue, modelPointerFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, meshPointerToScriptValue, meshPointerFromScriptValue);
|
||||
|
@ -645,50 +627,41 @@ namespace scriptable {
|
|||
|
||||
return metaTypeIds.size();
|
||||
}
|
||||
|
||||
// callback helper that lets C++ method signatures remain simple (ie: taking a single callback argument) while
|
||||
// still supporting extended Qt signal-like (scope, "methodName") and (scope, function(){}) "this" binding conventions
|
||||
QScriptValue jsBindCallback(QScriptValue callback) {
|
||||
if (callback.isObject() && callback.property("callback").isFunction()) {
|
||||
return callback;
|
||||
QScriptValue jsBindCallback(QScriptValue value) {
|
||||
if (value.isObject() && value.property("callback").isFunction()) {
|
||||
// value is already a bound callback
|
||||
return value;
|
||||
}
|
||||
auto engine = callback.engine();
|
||||
auto engine = value.engine();
|
||||
auto context = engine ? engine->currentContext() : nullptr;
|
||||
auto length = context ? context->argumentCount() : 0;
|
||||
QScriptValue scope = context ? context->thisObject() : QScriptValue::NullValue;
|
||||
QScriptValue method;
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "jsBindCallback" << engine << length << scope.toQObject() << method.toString();
|
||||
int i = 0;
|
||||
for (; context && i < length; i++) {
|
||||
if (context->argument(i).strictlyEquals(callback)) {
|
||||
#endif
|
||||
|
||||
// find position in the incoming JS Function.arguments array (so we can test for the two-argument case)
|
||||
for (int i = 0; context && i < length; i++) {
|
||||
if (context->argument(i).strictlyEquals(value)) {
|
||||
method = context->argument(i+1);
|
||||
}
|
||||
}
|
||||
if (method.isFunction() || method.isString()) {
|
||||
scope = callback;
|
||||
// interpret as `API.func(..., scope, function callback(){})` or `API.func(..., scope, "methodName")`
|
||||
scope = value;
|
||||
} else {
|
||||
method = callback;
|
||||
// interpret as `API.func(..., function callback(){})`
|
||||
method = value;
|
||||
}
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "scope:" << scope.toQObject() << "method:" << method.toString();
|
||||
#endif
|
||||
return ::makeScopedHandlerObject(scope, method);
|
||||
}
|
||||
}
|
||||
|
||||
bool scriptable::GraphicsScriptingInterface::updateMeshPart(ScriptableMeshPointer mesh, ScriptableMeshPartPointer part) {
|
||||
Q_ASSERT(mesh);
|
||||
Q_ASSERT(part);
|
||||
Q_ASSERT(part->parentMesh);
|
||||
auto tmp = exportMeshPart(mesh, part->partIndex);
|
||||
if (part->parentMesh == mesh) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "updateMeshPart -- update via clone" << mesh << part;
|
||||
#endif
|
||||
tmp->replaceMeshData(part->cloneMeshPart());
|
||||
return false;
|
||||
} else {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "updateMeshPart -- update via inplace" << mesh << part;
|
||||
#endif
|
||||
tmp->replaceMeshData(part);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#include "ScriptableMesh.moc"
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ScriptableModel.h"
|
||||
|
@ -26,25 +33,26 @@ namespace scriptable {
|
|||
Q_PROPERTY(uint32 numAttributes READ getNumAttributes)
|
||||
Q_PROPERTY(uint32 numVertices READ getNumVertices)
|
||||
Q_PROPERTY(uint32 numIndices READ getNumIndices)
|
||||
Q_PROPERTY(QVariantMap metadata MEMBER metadata)
|
||||
Q_PROPERTY(QVector<QString> attributeNames READ getAttributeNames)
|
||||
Q_PROPERTY(QVector<scriptable::ScriptableMeshPartPointer> parts READ getMeshParts)
|
||||
Q_PROPERTY(bool valid READ hasValidMesh)
|
||||
bool hasValidMesh() const { return (bool)getMeshPointer(); }
|
||||
Q_PROPERTY(bool validOwned READ hasValidOwnedMesh)
|
||||
bool hasValidOwnedMesh() const { return (bool)getOwnedMeshPointer(); }
|
||||
Q_PROPERTY(bool strong READ hasValidStrongMesh)
|
||||
|
||||
operator const ScriptableMeshBase*() const { return (qobject_cast<const scriptable::ScriptableMeshBase*>(this)); }
|
||||
ScriptableMesh(scriptable::MeshPointer mesh) : ScriptableMeshBase(mesh), QScriptable() { ownedMesh = mesh; }
|
||||
ScriptableMesh(WeakModelProviderPointer provider, ScriptableModelBasePointer model, MeshPointer mesh, const QVariantMap& metadata)
|
||||
: ScriptableMeshBase(provider, model, mesh, metadata), QScriptable() { ownedMesh = mesh; }
|
||||
|
||||
ScriptableMesh(WeakModelProviderPointer provider, ScriptableModelBasePointer model, MeshPointer mesh, QObject* parent)
|
||||
: ScriptableMeshBase(provider, model, mesh, parent), QScriptable() { strongMesh = mesh; }
|
||||
ScriptableMesh(MeshPointer mesh, QObject* parent)
|
||||
: ScriptableMeshBase(WeakModelProviderPointer(), nullptr, mesh, parent), QScriptable() { strongMesh = mesh; }
|
||||
ScriptableMesh(const ScriptableMeshBase& other);
|
||||
ScriptableMesh(const ScriptableMesh& other) : ScriptableMeshBase(other), QScriptable() {};
|
||||
virtual ~ScriptableMesh();
|
||||
|
||||
Q_INVOKABLE const scriptable::ScriptableModelPointer getParentModel() const { return qobject_cast<scriptable::ScriptableModel*>(model); }
|
||||
Q_INVOKABLE const scriptable::MeshPointer getOwnedMeshPointer() const { return ownedMesh; }
|
||||
Q_INVOKABLE const scriptable::MeshPointer getOwnedMeshPointer() const { return strongMesh; }
|
||||
scriptable::ScriptableMeshPointer getSelf() const { return const_cast<scriptable::ScriptableMesh*>(this); }
|
||||
bool hasValidMesh() const { return !weakMesh.expired(); }
|
||||
bool hasValidStrongMesh() const { return (bool)strongMesh; }
|
||||
public slots:
|
||||
uint32 getNumParts() const;
|
||||
uint32 getNumVertices() const;
|
||||
|
@ -65,9 +73,9 @@ namespace scriptable {
|
|||
|
||||
int _getSlotNumber(const QString& attributeName) const;
|
||||
|
||||
scriptable::ScriptableMeshPointer cloneMesh(bool recalcNormals = false);
|
||||
scriptable::ScriptableMeshPointer cloneMesh(bool recalcNormals = false);
|
||||
public:
|
||||
operator bool() const { return !mesh.expired(); }
|
||||
operator bool() const { return !weakMesh.expired(); }
|
||||
|
||||
public slots:
|
||||
// QScriptEngine-specific wrappers
|
||||
|
@ -88,11 +96,9 @@ namespace scriptable {
|
|||
Q_PROPERTY(uint32 numIndices READ getNumIndices)
|
||||
Q_PROPERTY(QVector<QString> attributeNames READ getAttributeNames)
|
||||
|
||||
Q_PROPERTY(QVariantMap metadata MEMBER metadata)
|
||||
|
||||
ScriptableMeshPart(scriptable::ScriptableMeshPointer parentMesh, int partIndex);
|
||||
ScriptableMeshPart& operator=(const ScriptableMeshPart& view) { parentMesh=view.parentMesh; return *this; };
|
||||
ScriptableMeshPart(const ScriptableMeshPart& other) : QObject(), QScriptable(), parentMesh(other.parentMesh), partIndex(other.partIndex) {}
|
||||
ScriptableMeshPart(const ScriptableMeshPart& other) : QObject(other.parent()), QScriptable(), parentMesh(other.parentMesh), partIndex(other.partIndex) {}
|
||||
|
||||
public slots:
|
||||
scriptable::ScriptableMeshPointer getParentMesh() const { return parentMesh; }
|
||||
|
@ -134,23 +140,10 @@ namespace scriptable {
|
|||
public:
|
||||
scriptable::ScriptableMeshPointer parentMesh;
|
||||
uint32 partIndex;
|
||||
QVariantMap metadata;
|
||||
protected:
|
||||
int _elementsPerFace{ 3 };
|
||||
QString _topology{ "triangles" };
|
||||
scriptable::MeshPointer getMeshPointer() const { return parentMesh ? parentMesh->getMeshPointer() : nullptr; }
|
||||
};
|
||||
|
||||
class GraphicsScriptingInterface : public QObject, QScriptable {
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsScriptingInterface(QObject* parent = nullptr) : QObject(parent), QScriptable() {}
|
||||
GraphicsScriptingInterface(const GraphicsScriptingInterface& other) : QObject(), QScriptable() {}
|
||||
public slots:
|
||||
ScriptableMeshPartPointer exportMeshPart(ScriptableMeshPointer mesh, int part=0) {
|
||||
return ScriptableMeshPartPointer(new ScriptableMeshPart(mesh, part));
|
||||
}
|
||||
bool updateMeshPart(ScriptableMeshPointer mesh, ScriptableMeshPartPointer part);
|
||||
scriptable::MeshPointer getMeshPointer() const { return parentMesh ? parentMesh->getMeshPointer() : nullptr; }
|
||||
};
|
||||
|
||||
// callback helper that lets C++ method signatures remain simple (ie: taking a single callback argument) while
|
||||
|
@ -165,26 +158,5 @@ Q_DECLARE_METATYPE(scriptable::ScriptableMeshPointer)
|
|||
Q_DECLARE_METATYPE(QVector<scriptable::ScriptableMeshPointer>)
|
||||
Q_DECLARE_METATYPE(scriptable::ScriptableMeshPartPointer)
|
||||
Q_DECLARE_METATYPE(QVector<scriptable::ScriptableMeshPartPointer>)
|
||||
Q_DECLARE_METATYPE(scriptable::GraphicsScriptingInterface)
|
||||
|
||||
// FIXME: MESHFACES: faces were supported in the original Model.* API -- are they still needed/used/useful for anything yet?
|
||||
#include <memory>
|
||||
|
||||
namespace mesh {
|
||||
class MeshFace;
|
||||
using MeshFaces = QVector<mesh::MeshFace>;
|
||||
class MeshFace {
|
||||
public:
|
||||
MeshFace() {}
|
||||
MeshFace(QVector<scriptable::uint32> vertexIndices) : vertexIndices(vertexIndices) {}
|
||||
~MeshFace() {}
|
||||
|
||||
QVector<scriptable::uint32> vertexIndices;
|
||||
// TODO -- material...
|
||||
};
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(mesh::MeshFace)
|
||||
Q_DECLARE_METATYPE(QVector<mesh::MeshFace>)
|
||||
Q_DECLARE_METATYPE(scriptable::uint32)
|
||||
Q_DECLARE_METATYPE(QVector<scriptable::uint32>)
|
||||
|
|
|
@ -13,25 +13,13 @@
|
|||
#include "ScriptableMesh.h"
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
//#include "ScriptableModel.moc"
|
||||
|
||||
void scriptable::ScriptableModelBase::mixin(const QVariantMap& modelMetaData) {
|
||||
for (const auto& key : modelMetaData.keys()) {
|
||||
const auto& value = modelMetaData[key];
|
||||
if (metadata.contains(key) && metadata[key].type() == (QVariant::Type)QMetaType::QVariantList) {
|
||||
qCDebug(graphics_scripting) << "CONCATENATING" << key << metadata[key].toList().size() << "+" << value.toList().size();
|
||||
metadata[key] = metadata[key].toList() + value.toList();
|
||||
} else {
|
||||
metadata[key] = modelMetaData[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
// #define SCRIPTABLE_MESH_DEBUG 1
|
||||
|
||||
scriptable::ScriptableModelBase& scriptable::ScriptableModelBase::operator=(const scriptable::ScriptableModelBase& other) {
|
||||
provider = other.provider;
|
||||
objectID = other.objectID;
|
||||
metadata = other.metadata;
|
||||
for (auto& mesh : other.meshes) {
|
||||
for (const auto& mesh : other.meshes) {
|
||||
append(mesh);
|
||||
}
|
||||
return *this;
|
||||
|
@ -43,36 +31,27 @@ scriptable::ScriptableModelBase::~ScriptableModelBase() {
|
|||
#endif
|
||||
// makes cleanup order more deterministic to help with debugging
|
||||
for (auto& m : meshes) {
|
||||
m.ownedMesh.reset();
|
||||
m.strongMesh.reset();
|
||||
}
|
||||
meshes.clear();
|
||||
}
|
||||
|
||||
void scriptable::ScriptableModelBase::append(scriptable::WeakMeshPointer mesh, const QVariantMap& metadata) {
|
||||
meshes << ScriptableMeshBase{ provider, this, mesh, metadata };
|
||||
void scriptable::ScriptableModelBase::append(scriptable::WeakMeshPointer mesh) {
|
||||
meshes << ScriptableMeshBase{ provider, this, mesh, this /*parent*/ };
|
||||
}
|
||||
|
||||
void scriptable::ScriptableModelBase::append(const ScriptableMeshBase& mesh, const QVariantMap& modelMetaData) {
|
||||
void scriptable::ScriptableModelBase::append(const ScriptableMeshBase& mesh) {
|
||||
if (mesh.provider.lock().get() != provider.lock().get()) {
|
||||
qCDebug(graphics_scripting) << "warning: appending mesh from different provider..." << mesh.provider.lock().get() << " != " << provider.lock().get();
|
||||
}
|
||||
meshes << mesh;
|
||||
mixin(modelMetaData);
|
||||
}
|
||||
|
||||
void scriptable::ScriptableModelBase::append(const ScriptableModelBase& other, const QVariantMap& modelMetaData) {
|
||||
for (const auto& mesh : other.meshes) {
|
||||
append(mesh);
|
||||
}
|
||||
mixin(other.metadata);
|
||||
mixin(modelMetaData);
|
||||
}
|
||||
|
||||
|
||||
QString scriptable::ScriptableModel::toString() const {
|
||||
return QString("[ScriptableModel%1%2]")
|
||||
return QString("[ScriptableModel%1%2 numMeshes=%3]")
|
||||
.arg(objectID.isNull() ? "" : " objectID="+objectID.toString())
|
||||
.arg(objectName().isEmpty() ? "" : " name=" +objectName());
|
||||
.arg(objectName().isEmpty() ? "" : " name=" +objectName())
|
||||
.arg(meshes.size());
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelPointer scriptable::ScriptableModel::cloneModel(const QVariantMap& options) {
|
||||
|
@ -131,3 +110,5 @@ quint32 scriptable::ScriptableModel::mapAttributeValues(QScriptValue callback) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#include "ScriptableModel.moc"
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Forward.h"
|
||||
#include "GraphicsScriptingUtil.h"
|
||||
|
||||
class QScriptValue;
|
||||
|
||||
namespace scriptable {
|
||||
class ScriptableModel : public ScriptableModelBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_PROPERTY(QUuid objectID MEMBER objectID CONSTANT)
|
||||
Q_PROPERTY(QVariantMap metadata MEMBER metadata CONSTANT)
|
||||
Q_PROPERTY(uint32 numMeshes READ getNumMeshes)
|
||||
Q_PROPERTY(QVector<scriptable::ScriptableMeshPointer> meshes READ getMeshes)
|
||||
|
||||
|
@ -27,11 +34,9 @@ namespace scriptable {
|
|||
QVector<scriptable::ScriptableMeshPointer> getMeshes();
|
||||
const QVector<scriptable::ScriptableMeshPointer> getConstMeshes() const;
|
||||
operator scriptable::ScriptableModelBasePointer() {
|
||||
QPointer<scriptable::ScriptableModelBase> p;
|
||||
p = qobject_cast<scriptable::ScriptableModelBase*>(this);
|
||||
return p;
|
||||
return QPointer<scriptable::ScriptableModelBase>(qobject_cast<scriptable::ScriptableModelBase*>(this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// QScriptEngine-specific wrappers
|
||||
Q_INVOKABLE uint32 mapAttributeValues(QScriptValue callback);
|
||||
|
|
|
@ -28,10 +28,6 @@ namespace glm {
|
|||
using hvec4 = glm::tvec4<glm::detail::hdata>;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
#include "../../graphics-scripting/src/graphics-scripting/DebugNames.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
QLoggingCategory bufferhelper_logging{ "hifi.bufferview" };
|
||||
}
|
||||
|
@ -109,9 +105,7 @@ bool buffer_helpers::fromVariant(const gpu::BufferView& view, quint32 index, con
|
|||
const auto dataType = element.getType();
|
||||
const auto byteLength = element.getSize();
|
||||
const auto BYTES_PER_ELEMENT = byteLength / vecN;
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
qCDebug(bufferhelper_logging) << "bufferViewElementFromVariant" << index << DebugNames::stringFrom(dataType) << BYTES_PER_ELEMENT << vecN;
|
||||
#endif
|
||||
|
||||
if (BYTES_PER_ELEMENT == 1) {
|
||||
switch(vecN) {
|
||||
case 2: setBufferViewElement<glm::u8vec2>(view, index, v); return true;
|
||||
|
@ -176,18 +170,12 @@ QVariant buffer_helpers::toVariant(const gpu::BufferView& view, quint32 index, b
|
|||
auto byteOffset = index * vecN * BYTES_PER_ELEMENT;
|
||||
auto maxByteOffset = (view._size - 1) * vecN * BYTES_PER_ELEMENT;
|
||||
if (byteOffset > maxByteOffset) {
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
qDebug() << "toVariant -- " << DebugNames::stringFrom(dataType)
|
||||
#endif
|
||||
qDebug() << "toVariant -- byteOffset out of range " << byteOffset << " < " << maxByteOffset;
|
||||
qDebug() << "toVariant -- index: " << index << "numElements" << view.getNumElements();
|
||||
qDebug() << "toVariant -- vecN: " << vecN << "byteLength" << byteLength << "BYTES_PER_ELEMENT" << BYTES_PER_ELEMENT;
|
||||
}
|
||||
Q_ASSERT(byteOffset <= maxByteOffset);
|
||||
}
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
qCDebug(bufferhelper_logging) << "toVariant -- " << index << DebugNames::stringFrom(dataType) << BYTES_PER_ELEMENT << vecN;
|
||||
#endif
|
||||
if (BYTES_PER_ELEMENT == 1) {
|
||||
switch(vecN) {
|
||||
case 2: return getBufferViewElement<glm::u8vec2>(view, index, asArray);
|
||||
|
@ -305,13 +293,8 @@ template <typename T> struct GpuScalarToGlm;
|
|||
|
||||
struct GpuToGlmAdapter {
|
||||
static float error(const QString& name, const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
QString debugName;
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
debugName = DebugNames::stringFrom(view._element.getType())
|
||||
#endif
|
||||
qDebug() << QString("GpuToGlmAdapter:: unhandled type=%1(element=%2(%3)) size=%4(per=%5) vec%6 hint=%7 #%8")
|
||||
qDebug() << QString("GpuToGlmAdapter:: unhandled type=%1(element=%2) size=%3(per=%4) vec%5 hint=%6 #%7")
|
||||
.arg(name)
|
||||
.arg(debugName)
|
||||
.arg(view._element.getType())
|
||||
.arg(view._element.getSize())
|
||||
.arg(view._element.getSize() / view._element.getScalarCount())
|
||||
|
@ -404,7 +387,7 @@ struct getVec {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
static T __to_scalar__(const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
static T __to_value__(const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
assert(boundsCheck(view, index));
|
||||
return FUNC::get(view, index, hint);
|
||||
}
|
||||
|
@ -425,18 +408,18 @@ template <> QVector<glm::vec4> buffer_helpers::toVector<glm::vec4>(const gpu::Bu
|
|||
}
|
||||
|
||||
|
||||
// indexed conversion accessors (similar to "view.convert<T>(i)" existed)
|
||||
// indexed conversion accessors (like the hypothetical "view.convert<T>(i)")
|
||||
template <> int buffer_helpers::convert<int>(const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
return getVec<GpuScalarToGlm<int>,int>::__to_scalar__(view, index, hint);
|
||||
return getVec<GpuScalarToGlm<int>,int>::__to_value__(view, index, hint);
|
||||
}
|
||||
template <> glm::vec2 buffer_helpers::convert<glm::vec2>(const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
return getVec<GpuVec2ToGlm<glm::vec2>,glm::vec2>::__to_scalar__(view, index, hint);
|
||||
return getVec<GpuVec2ToGlm<glm::vec2>,glm::vec2>::__to_value__(view, index, hint);
|
||||
}
|
||||
template <> glm::vec3 buffer_helpers::convert<glm::vec3>(const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
return getVec<GpuVec3ToGlm<glm::vec3>,glm::vec3>::__to_scalar__(view, index, hint);
|
||||
return getVec<GpuVec3ToGlm<glm::vec3>,glm::vec3>::__to_value__(view, index, hint);
|
||||
}
|
||||
template <> glm::vec4 buffer_helpers::convert<glm::vec4>(const gpu::BufferView& view, quint32 index, const char *hint) {
|
||||
return getVec<GpuVec4ToGlm<glm::vec4>,glm::vec4>::__to_scalar__(view, index, hint);
|
||||
return getVec<GpuVec4ToGlm<glm::vec4>,glm::vec4>::__to_value__(view, index, hint);
|
||||
}
|
||||
|
||||
gpu::BufferView buffer_helpers::clone(const gpu::BufferView& input) {
|
||||
|
@ -492,9 +475,6 @@ namespace {
|
|||
vsize > bufferView._size
|
||||
);
|
||||
QString hint = QString("%1").arg(slot);
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
hint = DebugNames::stringFrom(slot);
|
||||
#endif
|
||||
#ifdef DEV_BUILD
|
||||
auto beforeCount = bufferView.getNumElements();
|
||||
auto beforeTotal = bufferView._size;
|
||||
|
@ -519,9 +499,6 @@ namespace {
|
|||
auto afterTotal = bufferView._size;
|
||||
if (beforeTotal != afterTotal || beforeCount != afterCount) {
|
||||
QString typeName = QString("%1").arg(bufferView._element.getType());
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
typeName = DebugNames::stringFrom(bufferView._element.getType());
|
||||
#endif
|
||||
qCDebug(bufferhelper_logging, "NOTE:: _expandedAttributeBuffer.%s vec%d %s (before count=%lu bytes=%lu // after count=%lu bytes=%lu)",
|
||||
hint.toStdString().c_str(), bufferView._element.getScalarCount(),
|
||||
typeName.toStdString().c_str(), beforeCount, beforeTotal, afterCount, afterTotal);
|
||||
|
@ -557,9 +534,6 @@ std::map<QString, gpu::BufferView> buffer_helpers::gatherBufferViews(graphics::M
|
|||
if (beforeCount > 0) {
|
||||
auto element = view._element;
|
||||
QString typeName = QString("%1").arg(element.getType());
|
||||
#ifdef DEBUG_BUFFERVIEW_SCRIPTING
|
||||
typeName = DebugNames::stringFrom(element.getType());
|
||||
#endif
|
||||
|
||||
attributeViews[name] = getBufferView(mesh, slot);
|
||||
|
||||
|
|
|
@ -492,7 +492,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
|||
{ "v2", vec3toVariant(bestModelTriangle.v2) },
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,38 +590,41 @@ MeshProxyList Model::getMeshes() const {
|
|||
// FIXME: temporary workaround that updates the whole FBXGeometry (to keep findRayIntersection in sync)
|
||||
#include "Model_temporary_hack.cpp.h"
|
||||
|
||||
bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer _newModel, int meshIndex, int partIndex) {
|
||||
bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer newModel, int meshIndex, int partIndex) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
if (!isLoaded()) {
|
||||
qDebug() << "!isLoaded" << this;
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// FIXME: temporary workaround for updating the whole FBXGeometry (to keep findRayIntersection in sync)
|
||||
auto newRenderGeometry = new MyGeometryMappingResource(
|
||||
_url, _renderGeometry, _newModel ? scriptable::make_qtowned<scriptable::ScriptableModelBase>(*_newModel) : nullptr
|
||||
);
|
||||
_visualGeometryRequestFailed = false;
|
||||
deleteGeometry();
|
||||
_renderGeometry.reset(newRenderGeometry);
|
||||
_rig.destroyAnimGraph();
|
||||
updateGeometry();
|
||||
calculateTriangleSets();
|
||||
_needsReload = false;
|
||||
_needsFixupInScene = true;
|
||||
setRenderItemsNeedUpdate();
|
||||
if (!newModel || !newModel->meshes.size()) {
|
||||
qDebug() << "!newModel.meshes.size()" << this;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto resource = new MyGeometryResource(_url, _renderGeometry, newModel);
|
||||
_needsReload = false;
|
||||
_needsUpdateTextures = false;
|
||||
_visualGeometryRequestFailed = false;
|
||||
_needsFixupInScene = true;
|
||||
|
||||
invalidCalculatedMeshBoxes();
|
||||
deleteGeometry();
|
||||
_renderGeometry.reset(resource);
|
||||
updateGeometry();
|
||||
calculateTriangleSets();
|
||||
setRenderItemsNeedUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase Model::getScriptableModel(bool* ok) {
|
||||
scriptable::ScriptableModelBase Model::getScriptableModel() {
|
||||
QMutexLocker lock(&_mutex);
|
||||
scriptable::ScriptableModelBase result;
|
||||
|
||||
if (!isLoaded()) {
|
||||
qCDebug(renderutils) << "Model::getScriptableModel -- !isLoaded";
|
||||
return scriptable::ModelProvider::modelUnavailableError(ok);
|
||||
return result;
|
||||
}
|
||||
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
|
@ -630,22 +632,9 @@ scriptable::ScriptableModelBase Model::getScriptableModel(bool* ok) {
|
|||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& fbxMesh = geometry.meshes.at(i);
|
||||
if (auto mesh = fbxMesh._mesh) {
|
||||
auto name = geometry.getModelNameOfMesh(i);
|
||||
result.append(std::const_pointer_cast<graphics::Mesh>(mesh), {
|
||||
{ "index", i },
|
||||
{ "name", name },
|
||||
{ "meshIndex", fbxMesh.meshIndex },
|
||||
{ "displayName", QString::fromStdString(mesh->displayName) },
|
||||
{ "modelName", QString::fromStdString(mesh->modelName) },
|
||||
{ "modelTransform", buffer_helpers::toVariant(fbxMesh.modelTransform) },
|
||||
{ "transform", buffer_helpers::toVariant(geometry.offset * fbxMesh.modelTransform) },
|
||||
{ "extents", buffer_helpers::toVariant(fbxMesh.meshExtents) },
|
||||
});
|
||||
result.append(mesh);
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -317,7 +317,7 @@ public:
|
|||
int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); }
|
||||
int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel(bool* ok = nullptr) override;
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override;
|
||||
|
||||
void scaleToFit();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include <graphics/BufferViewHelpers.h>
|
||||
#include <graphics-scripting/GraphicsScriptingUtil.h>
|
||||
class MyGeometryMappingResource : public GeometryResource {
|
||||
class MyGeometryResource : public GeometryResource {
|
||||
public:
|
||||
shared_ptr<FBXGeometry> fbxGeometry;
|
||||
MyGeometryMappingResource(const QUrl& url, Geometry::Pointer originalGeometry, std::shared_ptr<scriptable::ScriptableModelBase> newModel) : GeometryResource(url) {
|
||||
MyGeometryResource(const QUrl& url, Geometry::Pointer originalGeometry, scriptable::ScriptableModelBasePointer newModel) : GeometryResource(url) {
|
||||
fbxGeometry = std::make_shared<FBXGeometry>();
|
||||
FBXGeometry& geometry = *fbxGeometry.get();
|
||||
const FBXGeometry* original;
|
||||
|
@ -15,41 +15,12 @@ public:
|
|||
original = tmpGeometry.get();
|
||||
}
|
||||
geometry.originalURL = original->originalURL;
|
||||
geometry.bindExtents = original->bindExtents;
|
||||
|
||||
geometry.author = original->author;
|
||||
geometry.applicationName = original->applicationName;
|
||||
for (const auto &j : original->joints) {
|
||||
geometry.joints << j;
|
||||
}
|
||||
geometry.jointIndices = QHash<QString,int>{ original->jointIndices };
|
||||
|
||||
geometry.animationFrames = QVector<FBXAnimationFrame>{ original->animationFrames };
|
||||
geometry.meshIndicesToModelNames = QHash<int, QString>{ original->meshIndicesToModelNames };
|
||||
geometry.blendshapeChannelNames = QList<QString>{ original->blendshapeChannelNames };
|
||||
|
||||
geometry.hasSkeletonJoints = original->hasSkeletonJoints;
|
||||
geometry.offset = original->offset;
|
||||
geometry.leftEyeJointIndex = original->leftEyeJointIndex;
|
||||
geometry.rightEyeJointIndex = original->rightEyeJointIndex;
|
||||
geometry.neckJointIndex = original->neckJointIndex;
|
||||
geometry.rootJointIndex = original->rootJointIndex;
|
||||
geometry.leanJointIndex = original->leanJointIndex;
|
||||
geometry.headJointIndex = original->headJointIndex;
|
||||
geometry.leftHandJointIndex = original->leftHandJointIndex;
|
||||
geometry.rightHandJointIndex = original->rightHandJointIndex;
|
||||
geometry.leftToeJointIndex = original->leftToeJointIndex;
|
||||
geometry.rightToeJointIndex = original->rightToeJointIndex;
|
||||
geometry.leftEyeSize = original->leftEyeSize;
|
||||
geometry.rightEyeSize = original->rightEyeSize;
|
||||
geometry.humanIKJointIndices = original->humanIKJointIndices;
|
||||
geometry.palmDirection = original->palmDirection;
|
||||
geometry.neckPivot = original->neckPivot;
|
||||
geometry.bindExtents = original->bindExtents;
|
||||
|
||||
// Copy materials
|
||||
QHash<QString, size_t> materialIDAtlas;
|
||||
for (const FBXMaterial& material : original->materials) {
|
||||
materialIDAtlas[material.materialID] = _materials.size();
|
||||
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
|
||||
}
|
||||
std::shared_ptr<GeometryMeshes> meshes = std::make_shared<GeometryMeshes>();
|
||||
|
@ -58,6 +29,7 @@ public:
|
|||
if (newModel) {
|
||||
geometry.meshExtents.reset();
|
||||
for (const auto& newMesh : newModel->meshes) {
|
||||
// qDebug() << "newMesh #" << meshID;
|
||||
FBXMesh mesh;
|
||||
if (meshID < original->meshes.size()) {
|
||||
mesh = original->meshes.at(meshID); // copy
|
||||
|
@ -73,7 +45,7 @@ public:
|
|||
mesh.createBlendShapeTangents(false);
|
||||
geometry.meshes << mesh;
|
||||
// Copy mesh pointers
|
||||
meshes->emplace_back(newMesh.getMeshPointer());//buffer_helpers::cloneMesh(ptr));
|
||||
meshes->emplace_back(newMesh.getMeshPointer());
|
||||
int partID = 0;
|
||||
const auto oldParts = mesh.parts;
|
||||
mesh.parts.clear();
|
||||
|
@ -83,7 +55,7 @@ public:
|
|||
// Construct local parts
|
||||
part.triangleIndices = buffer_helpers::toVector<int>(mesh._mesh->getIndexBuffer(), "part.triangleIndices");
|
||||
mesh.parts << part;
|
||||
auto p = std::make_shared<MeshPart>(meshID, partID, (int)materialIDAtlas[part.materialID]);
|
||||
auto p = std::make_shared<MeshPart>(meshID, partID, 0);
|
||||
parts->push_back(p);
|
||||
partID++;
|
||||
}
|
||||
|
@ -94,20 +66,18 @@ public:
|
|||
glm::vec3 transformedVertex = glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f));
|
||||
geometry.meshExtents.minimum = glm::min(geometry.meshExtents.minimum, transformedVertex);
|
||||
geometry.meshExtents.maximum = glm::max(geometry.meshExtents.maximum, transformedVertex);
|
||||
|
||||
|
||||
mesh.meshExtents.minimum = glm::min(mesh.meshExtents.minimum, transformedVertex);
|
||||
mesh.meshExtents.maximum = glm::max(mesh.meshExtents.maximum, transformedVertex);
|
||||
}
|
||||
}
|
||||
|
||||
meshID++;
|
||||
}
|
||||
}
|
||||
_meshes = meshes;
|
||||
_meshParts = parts;
|
||||
_animGraphOverrideUrl = originalGeometry ? originalGeometry->getAnimGraphOverrideUrl() : QUrl();
|
||||
_loaded = true;
|
||||
_fbxGeometry = fbxGeometry;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
138
tools/jsdoc/package-lock.json
generated
138
tools/jsdoc/package-lock.json
generated
|
@ -1,138 +0,0 @@
|
|||
{
|
||||
"name": "hifiJSDoc",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"babylon": {
|
||||
"version": "7.0.0-beta.19",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
|
||||
"integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A=="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
|
||||
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
|
||||
},
|
||||
"catharsis": {
|
||||
"version": "0.8.9",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
|
||||
"integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
|
||||
"requires": {
|
||||
"underscore-contrib": "0.3.0"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||
},
|
||||
"js2xmlparser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
|
||||
"integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
|
||||
"requires": {
|
||||
"xmlcreate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"jsdoc": {
|
||||
"version": "3.5.5",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
|
||||
"integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
|
||||
"requires": {
|
||||
"babylon": "7.0.0-beta.19",
|
||||
"bluebird": "3.5.1",
|
||||
"catharsis": "0.8.9",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"js2xmlparser": "3.0.0",
|
||||
"klaw": "2.0.0",
|
||||
"marked": "0.3.12",
|
||||
"mkdirp": "0.5.1",
|
||||
"requizzle": "0.2.1",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"taffydb": "2.6.2",
|
||||
"underscore": "1.8.3"
|
||||
}
|
||||
},
|
||||
"klaw": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
|
||||
"integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=",
|
||||
"requires": {
|
||||
"graceful-fs": "4.1.11"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.3.12",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz",
|
||||
"integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA=="
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"requizzle": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
|
||||
"integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
|
||||
"requires": {
|
||||
"underscore": "1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"underscore": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
|
||||
"integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag="
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
|
||||
},
|
||||
"taffydb": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
|
||||
"integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
|
||||
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
|
||||
},
|
||||
"underscore-contrib": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
|
||||
"integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
|
||||
"requires": {
|
||||
"underscore": "1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"underscore": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
|
||||
"integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag="
|
||||
}
|
||||
}
|
||||
},
|
||||
"xmlcreate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
|
||||
"integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8="
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue