From b5cbd7720e6ddb5e4fe711886ea3e3cd2c41ce57 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 1 Apr 2016 14:56:56 -0700 Subject: [PATCH 1/2] Lock entity tree on export, and clipboard on import. --- interface/src/Application.cpp | 105 ++++++++++++++------------ libraries/entities/src/EntityTree.cpp | 6 +- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ffc9b0333c..9d4a5e37e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2815,60 +2815,68 @@ bool Application::exportEntities(const QString& filename, const QVectorgetTree(); auto exportTree = std::make_shared(); exportTree->createRootElement(); - glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE); - for (auto entityID : entityIDs) { // Gather entities and properties. - auto entityItem = entityTree->findEntityByEntityItemID(entityID); - if (!entityItem) { - qCWarning(interfaceapp) << "Skipping export of" << entityID << "that is not in scene."; - continue; - } - - if (!givenOffset) { - EntityItemID parentID = entityItem->getParentID(); - if (parentID.isInvalidID() || !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID)) { - auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties. - root.x = glm::min(root.x, position.x); - root.y = glm::min(root.y, position.y); - root.z = glm::min(root.z, position.z); + bool success = true; + entityTree->withReadLock([&] { + for (auto entityID : entityIDs) { // Gather entities and properties. + auto entityItem = entityTree->findEntityByEntityItemID(entityID); + if (!entityItem) { + qCWarning(interfaceapp) << "Skipping export of" << entityID << "that is not in scene."; + continue; } + + if (!givenOffset) { + EntityItemID parentID = entityItem->getParentID(); + if (parentID.isInvalidID() || !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID)) { + auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties. + root.x = glm::min(root.x, position.x); + root.y = glm::min(root.y, position.y); + root.z = glm::min(root.z, position.z); + } + } + entities[entityID] = entityItem; } - entities[entityID] = entityItem; - } - if (entities.size() == 0) { - return false; - } + if (entities.size() == 0) { + success = false; + return; + } - if (givenOffset) { - root = *givenOffset; - } - for (EntityItemPointer& entityDatum : entities) { - auto properties = entityDatum->getProperties(); - EntityItemID parentID = properties.getParentID(); - if (parentID.isInvalidID()) { - properties.setPosition(properties.getPosition() - root); - } else if (!entities.contains(parentID)) { - entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root); - } // else valid parent -- don't offset - exportTree->addEntity(entityDatum->getEntityItemID(), properties); - } + if (givenOffset) { + root = *givenOffset; + } + for (EntityItemPointer& entityDatum : entities) { + auto properties = entityDatum->getProperties(); + EntityItemID parentID = properties.getParentID(); + if (parentID.isInvalidID()) { + properties.setPosition(properties.getPosition() - root); + } + else if (!entities.contains(parentID)) { + entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root); + } // else valid parent -- don't offset + exportTree->addEntity(entityDatum->getEntityItemID(), properties); + } + }); + if (success) { + exportTree->writeToJSONFile(filename.toLocal8Bit().constData()); - exportTree->writeToJSONFile(filename.toLocal8Bit().constData()); - - // restore the main window's active state - _window->activateWindow(); - return true; + // restore the main window's active state + _window->activateWindow(); + } + return success; } bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { glm::vec3 offset(x, y, z); QVector entities; QVector ids; - getEntities()->getTree()->findEntities(AACube(offset, scale), entities); - foreach(EntityItemPointer entity, entities) { - ids << entity->getEntityItemID(); - } + auto entityTree = getEntities()->getTree(); + entityTree->withReadLock([&] { + entityTree->findEntities(AACube(offset, scale), entities); + foreach(EntityItemPointer entity, entities) { + ids << entity->getEntityItemID(); + } + }); return exportEntities(filename, ids, &offset); } @@ -2898,12 +2906,15 @@ void Application::saveSettings() { } bool Application::importEntities(const QString& urlOrFilename) { - _entityClipboard->eraseAllOctreeElements(); + bool success = false; + _entityClipboard->withWriteLock([&] { + _entityClipboard->eraseAllOctreeElements(); - bool success = _entityClipboard->readFromURL(urlOrFilename); - if (success) { - _entityClipboard->reaverageOctreeElements(); - } + success = _entityClipboard->readFromURL(urlOrFilename); + if (success) { + _entityClipboard->reaverageOctreeElements(); + } + }); return success; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5292e12ae8..6d020941b5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1313,7 +1313,7 @@ void EntityTree::pruneTree() { } QVector EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree, - float x, float y, float z) { + float x, float y, float z) { SendEntitiesOperationArgs args; args.packetSender = packetSender; args.ourTree = this; @@ -1323,7 +1323,9 @@ QVector EntityTree::sendEntities(EntityEditPacketSender* packetSen // We need to keep a map so that we can map parent identifiers correctly. QHash map; args.map = ↦ - recurseTreeWithOperation(sendEntitiesOperation, &args); + withReadLock([&] { + recurseTreeWithOperation(sendEntitiesOperation, &args); + }); packetSender->releaseQueuedMessages(); return map.values().toVector(); From cec4175e9ddfe4e2c7c4eddc4da4aa1e3771dfd1 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 1 Apr 2016 15:00:51 -0700 Subject: [PATCH 2/2] whitespace --- libraries/entities/src/EntityTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 6d020941b5..92c3ce216f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1313,7 +1313,7 @@ void EntityTree::pruneTree() { } QVector EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree, - float x, float y, float z) { + float x, float y, float z) { SendEntitiesOperationArgs args; args.packetSender = packetSender; args.ourTree = this;