diff --git a/assignment-client/src/models/ModelServer.cpp b/assignment-client/src/models/ModelServer.cpp index ae6ffaf969..642c2f71db 100644 --- a/assignment-client/src/models/ModelServer.cpp +++ b/assignment-client/src/models/ModelServer.cpp @@ -65,6 +65,18 @@ void ModelServer::modelCreated(const ModelItem& newModel, const SharedNodePointe memcpy(copyAt, &modelID, sizeof(modelID)); copyAt += sizeof(modelID); packetLength += sizeof(modelID); + + // This would be a good place to fix our modelID to element map + ModelTree* tree = static_cast(_tree); + + // find and clear the map element with the creatorToken + ModelItemID creatorTokenModelItemID(modelID, creatorTokenID, true); + ModelTreeElement* element = tree->getContainingElement(creatorTokenModelItemID); + tree->setContainingElement(creatorTokenModelItemID, NULL); + + // find and clear the map element with the creatorToken + ModelItemID justModelID(modelID); + tree->setContainingElement(justModelID, element); NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, senderNode); } diff --git a/libraries/models/src/ModelItem.cpp b/libraries/models/src/ModelItem.cpp index bf40e6bb44..6c31920b06 100644 --- a/libraries/models/src/ModelItem.cpp +++ b/libraries/models/src/ModelItem.cpp @@ -771,6 +771,11 @@ int ModelItem::readModelDataFromBuffer(const unsigned char* data, int bytesLeftT } ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& processedBytes, ModelTree* tree, bool& valid) { + bool wantDebug = false; + if (wantDebug) { + qDebug() << "ModelItem ModelItem::fromEditPacket() length=" << length; + } + ModelItem newModelItem; // id and _lastUpdated will get set here... const unsigned char* dataAt = data; processedBytes = 0; @@ -779,6 +784,10 @@ ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& int octets = numberOfThreeBitSectionsInCode(data); int lengthOfOctcode = bytesRequiredForCodeLength(octets); + if (wantDebug) { + qDebug() << "ModelItem ModelItem::fromEditPacket() lengthOfOctcode=" << lengthOfOctcode; + } + // we don't actually do anything with this octcode... dataAt += lengthOfOctcode; processedBytes += lengthOfOctcode; @@ -789,6 +798,10 @@ ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& dataAt += sizeof(editID); processedBytes += sizeof(editID); + if (wantDebug) { + qDebug() << "ModelItem ModelItem::fromEditPacket() editID=" << editID; + } + bool isNewModelItem = (editID == NEW_MODEL); // special case for handling "new" modelItems @@ -811,7 +824,7 @@ ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& newModelItem = *existingModelItem; } else { // the user attempted to edit a modelItem that doesn't exist - qDebug() << "user attempted to edit a modelItem that doesn't exist..."; + qDebug() << "user attempted to edit a modelItem that doesn't exist... editID=" << editID; valid = false; return newModelItem; } diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 3e0daab64a..dce0dda27c 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -21,6 +21,11 @@ ModelTreeElement* ModelTree::createNewElement(unsigned char * octalCode) { return newElement; } +void ModelTree::eraseAllOctreeElements() { + _modelToElementMap.clear(); + Octree::eraseAllOctreeElements(); +} + bool ModelTree::handlesEditPacketType(PacketType packetType) const { // we handle these types of "edit" packets switch (packetType) { @@ -171,6 +176,13 @@ bool StoreModelOperator::PreRecursion(OctreeElement* element) { // correct element. if (!_containingElement->bestFitModelBounds(_newModel)) { modelTreeElement->removeModelWithModelItemID(_newModel.getModelItemID()); + + // If we haven't yet found the new location, then we need to + // make sure to remove our model to element map, because for + // now we're not in that map + if (!_foundNew) { + _tree->setContainingElement(_newModel.getModelItemID(), NULL); + } } _foundOld = true; } else { @@ -494,6 +506,15 @@ void ModelTree::findModels(const AACube& cube, QVector foundModels) const ModelItem* ModelTree::findModelByID(uint32_t id, bool alreadyLocked) const { ModelItemID modelID(id); + + bool wantDebug = false; + if (wantDebug) { + qDebug() << "ModelTree::findModelByID()..."; + qDebug() << " id=" << id; + qDebug() << " modelID=" << modelID; + qDebug() << "_modelToElementMap=" << _modelToElementMap; + } + return findModelByModelItemID(modelID); } @@ -793,7 +814,11 @@ ModelTreeElement* ModelTree::getContainingElement(const ModelItemID& modelItemID void ModelTree::setContainingElement(const ModelItemID& modelItemID, ModelTreeElement* element) { // TODO: do we need to make this thread safe? Or is it acceptable as is - _modelToElementMap[modelItemID] = element; + if (element) { + _modelToElementMap[modelItemID] = element; + } else { + _modelToElementMap.remove(modelItemID); + } //qDebug() << "setContainingElement() modelItemID=" << modelItemID << "element=" << element; //qDebug() << "AFTER _modelToElementMap=" << _modelToElementMap; diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index a41865af7d..16390a26e6 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -36,6 +36,7 @@ public: /// Type safe version of getRoot() ModelTreeElement* getRoot() { return static_cast(_rootElement); } + virtual void eraseAllOctreeElements(); // These methods will allow the OctreeServer to send your tree inbound edit packets of your // own definition. Implement these to allow your octree based server to support editing diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 06db647843..ac12b6a81b 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -22,6 +22,7 @@ ModelTreeElement::ModelTreeElement(unsigned char* octalCode) : OctreeElement(), }; ModelTreeElement::~ModelTreeElement() { + //qDebug() << "ModelTreeElement::~ModelTreeElement() this=" << this; _voxelMemoryUsage -= sizeof(ModelTreeElement); delete _modelItems; _modelItems = NULL; @@ -226,6 +227,7 @@ void ModelTreeElement::update(ModelTreeUpdateArgs& args) { markWithChangedTime(); // TODO: is this a good place to change the containing element map??? + qDebug() << "ModelTreeElement::update()... calling _myTree->setContainingElement(model.getModelItemID(), NULL); ********"; _myTree->setContainingElement(model.getModelItemID(), NULL); } else { @@ -526,6 +528,7 @@ bool ModelTreeElement::removeModelWithID(uint32_t id) { if ((*_modelItems)[i].getID() == id) { foundModel = true; _modelItems->removeAt(i); + break; } } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 822ac4dc9b..d020076bcf 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -222,7 +222,7 @@ public: OctreeElement* getRoot() { return _rootElement; } - void eraseAllOctreeElements(); + virtual void eraseAllOctreeElements(); void processRemoveOctreeElementsBitstream(const unsigned char* bitstream, int bufferSizeBytes); void readBitstreamToTree(const unsigned char* bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args);