diff --git a/examples/libraries/entityPropertyDialogBox.js b/examples/libraries/entityPropertyDialogBox.js index 01e0c76e0d..ef597549f2 100644 --- a/examples/libraries/entityPropertyDialogBox.js +++ b/examples/libraries/entityPropertyDialogBox.js @@ -54,6 +54,8 @@ EntityPropertyDialogBox = (function () { index++; array.push({ label: "Textures:", value: properties.textures }); index++; + array.push({ label: "Original Textures:\n" + properties.originalTextures, type: "header" }); + index++; } array.push({ label: "Position:", type: "header" }); index++; @@ -239,6 +241,7 @@ EntityPropertyDialogBox = (function () { properties.animationFPS = array[index++].value; properties.animationFrameIndex = array[index++].value; properties.textures = array[index++].value; + index++; // skip textureNames label } index++; // skip header properties.position.x = array[index++].value; diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 46406e9f5e..2f8ddb1095 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -61,11 +61,13 @@ EntityTreeRenderer::~EntityTreeRenderer() { void EntityTreeRenderer::clear() { OctreeRenderer::clear(); + _entityScripts.clear(); } void EntityTreeRenderer::init() { OctreeRenderer::init(); - static_cast(_tree)->setFBXService(this); + EntityTree* entityTree = static_cast(_tree); + entityTree->setFBXService(this); if (_wantScripts) { _entitiesScriptEngine = new ScriptEngine(NO_SCRIPT, "Entities", @@ -77,6 +79,8 @@ void EntityTreeRenderer::init() { // first chance, we'll check for enter/leave entity events. glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition(); _lastAvatarPosition = avatarPosition + glm::vec3(1.f, 1.f, 1.f); + + connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); } QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID) { @@ -762,4 +766,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI } } +void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { + _entityScripts.remove(entityID); +} diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index b8acb28c3b..ff9066dd6d 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -101,6 +101,9 @@ signals: void enterEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID); + +public slots: + void deletingEntity(const EntityItemID& entityID); private: QList _releasedModels; diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index ce8d497da3..3cee527273 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -62,10 +62,21 @@ void RenderableModelEntityItem::remapTextures() { return; // nothing to do if we don't have a model } + if (!_model->isLoadedWithTextures()) { + return; // nothing to do if the model has not yet loaded it's default textures + } + + if (!_originalTexturesRead && _model->isLoadedWithTextures()) { + const QSharedPointer& networkGeometry = _model->getGeometry(); + if (networkGeometry) { + _originalTextures = networkGeometry->getTextureNames(); + _originalTexturesRead = true; + } + } + if (_currentTextures == _textures) { return; // nothing to do if our recently mapped textures match our desired textures } - qDebug() << "void RenderableModelEntityItem::remapTextures()...."; // since we're changing here, we need to run through our current texture map // and any textures in the recently mapped texture, that is not in our desired @@ -234,6 +245,14 @@ bool RenderableModelEntityItem::needsSimulation() const { return _needsInitialSimulation || simulationState == Moving || simulationState == Changing; } +EntityItemProperties RenderableModelEntityItem::getProperties() const { + EntityItemProperties properties = ModelEntityItem::getProperties(); // get the properties from our base class + if (_originalTexturesRead) { + properties.setTextureNames(_originalTextures); + } + return properties; +} + diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index dbc77b7e48..48c9a26051 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -37,10 +37,12 @@ public: _model(NULL), _needsInitialSimulation(true), _needsModelReload(true), - _myRenderer(NULL) { } + _myRenderer(NULL), + _originalTexturesRead(false) { } virtual ~RenderableModelEntityItem(); + virtual EntityItemProperties getProperties() const; virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy); virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, @@ -59,6 +61,8 @@ private: bool _needsModelReload; EntityTreeRenderer* _myRenderer; QString _currentTextures; + QStringList _originalTextures; + bool _originalTexturesRead; }; #endif // hifi_RenderableModelEntityItem_h diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 1e53d06d7c..1742afba05 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -734,6 +734,32 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u } } +QStringList NetworkGeometry::getTextureNames() const { + QStringList result; + for (int i = 0; i < _meshes.size(); i++) { + const NetworkMesh& mesh = _meshes[i]; + for (int j = 0; j < mesh.parts.size(); j++) { + const NetworkMeshPart& part = mesh.parts[j]; + + if (!part.diffuseTextureName.isEmpty()) { + QString textureURL = part.diffuseTexture->getURL().toString(); + result << part.diffuseTextureName + ":" + textureURL; + } + + if (!part.normalTextureName.isEmpty()) { + QString textureURL = part.normalTexture->getURL().toString(); + result << part.normalTextureName + ":" + textureURL; + } + + if (!part.specularTextureName.isEmpty()) { + QString textureURL = part.specularTexture->getURL().toString(); + result << part.specularTextureName + ":" + textureURL; + } + } + } + return result; +} + /// Reads geometry in a worker thread. class GeometryReader : public QRunnable { public: diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 72d283c931..28f1341b5f 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -112,6 +112,7 @@ public: virtual void clearLoadPriority(const QPointer& owner); void setTextureWithNameToURL(const QString& name, const QUrl& url); + QStringList getTextureNames() const; protected: diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 11661b02f4..9032cebc77 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -243,6 +243,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons boundingBox.setProperty("dimensions", boundingBoxDimensions); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(boundingBox, boundingBox); // gettable, but not settable + QString textureNamesList = _textureNames.join(",\n"); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(originalTextures, textureNamesList); // gettable, but not settable + return properties; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 92fa344286..3ae2aa9c7a 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -285,6 +285,9 @@ public: const QString& getTextures() const { return _textures; } void setTextures(const QString& value) { _textures = value; _texturesChanged = true; } + + const QStringList& getTextureNames() const { return _textureNames; } + void setTextureNames(const QStringList& value) { _textureNames = value; } void setLastEdited(quint64 usecTime) { _lastEdited = usecTime; } @@ -381,6 +384,7 @@ private: // properties of model geometry. But these properties are not serialized like other properties. QVector _sittingPoints; glm::vec3 _naturalDimensions; + QStringList _textureNames; }; Q_DECLARE_METATYPE(EntityItemProperties); QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index f31f21ebe9..199bd92030 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -185,6 +185,8 @@ void EntityTree::trackDeletedEntity(const EntityItemID& entityID) { } void EntityTree::deleteEntity(const EntityItemID& entityID) { + emit deletingEntity(entityID); + // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(this, entityID); recurseTreeWithOperator(&theOperator); @@ -197,6 +199,7 @@ void EntityTree::deleteEntities(QSet entityIDs) { foreach(const EntityItemID& entityID, entityIDs) { // tell our delete operator about this entityID theOperator.addEntityIDToDeleteList(entityID); + emit deletingEntity(entityID); } recurseTreeWithOperator(&theOperator); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 53b407c7f5..8d1acc0d01 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -141,6 +141,9 @@ public: void trackDeletedEntity(const EntityItemID& entityID); QList& getMovingEntities() { return _movingEntities; } + +signals: + void deletingEntity(const EntityItemID& entityID); private: diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index d9520a4e68..496839fdcd 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -123,6 +123,8 @@ public: void setCache(ResourceCache* cache) { _cache = cache; } Q_INVOKABLE void allReferencesCleared(); + + const QUrl& getURL() const { return _url; } signals: