void Body::removePart(std::string part_uuid) { //Get shared pointer of the Part to be removed boost::shared_ptr<Part> part = getPartByUUID(part_uuid); //TODO: Handle removal of root BP or root Organ if (part == nullptr || part->getId() == "ROOT" || part->getId() == "UPPER_TORSO") { return; } debug_print("Removing Part %s...\n", part->getId().c_str()); //Create a list of all parts to be removed std::vector<string>* rem_list = new std::vector<string>(); //Add the part given to the function... rem_list->push_back(part_uuid); //...and everything that lies downstream of it (Organs and Bodyparts) makeDownstreamPartList(part_uuid, rem_list); //Remove duplicates from the list std::sort(rem_list->begin(), rem_list->end()); rem_list->erase(std::unique(rem_list->begin(), rem_list->end()), rem_list->end()); #ifdef _DEBUG for (auto it = rem_list->begin(); it != rem_list->end(); it++) { debug_print("UUID %s is Part %s \n", getPartByUUID(*it)->getUUID().c_str(), getPartByUUID(*it)->getId().c_str()); } #endif //Make a temporary list, in which UUIDs of empty bodyparts are stored. // Its contents are later added to the rem_list std::vector<string>* bp_rem = new std::vector<string>(); //Iterate over all parts to be removed... for (auto it_rl = rem_list->begin(); it_rl != rem_list->end(); it_rl++) { //...if the part is an Organ, remove it from its connectors connected_organs list if (getPartByUUID(*it_rl)->getType() == TYPE_ORGAN) { Organ *o = static_cast<Organ*>(getPartByUUID(*it_rl).get()); Organ *con = static_cast<Organ*>(getPartByUUID(o->getConnectorUUID()).get()); con->removeConnectedOrgan(*it_rl); } //..for all parts: remove from super part child list. // If the super part is found to be empty (removeChild() returns true), add it // to the temporary bp_rem list. BodyPart* super = static_cast<BodyPart*>(getPartByUUID(getPartByUUID(*it_rl)->getSuperPartUUID()).get()); BodyPart* old_super; if (super->removeChild(*it_rl)) { debug_print("BodyPart %s is empty, add to unregister\n", super->getId().c_str()); bp_rem->push_back(super->getUUID()); bool done = false; //For every BodyPart that is to be deleted as empty, remove it from its own // super BodyPart and check wheter it needs to be removed as well! while (!done) { old_super = super; super = static_cast<BodyPart*>(getPartByUUID(super->getSuperPartUUID()).get()); if (super->removeChild(old_super->getUUID())) { debug_print("BodyPart %s is empty, add to unregister\n", super->getId().c_str()); bp_rem->push_back(super->getUUID()); } else { done = true; } } } } //Merge the temporary removal list into the rem_list rem_list->insert(rem_list->end(), bp_rem->begin(), bp_rem->end()); //Remove duplicates again std::sort(rem_list->begin(), rem_list->end()); rem_list->erase(std::unique(rem_list->begin(), rem_list->end()), rem_list->end()); //Unregister the Parts, causing the shared pointers to destroy their references and themselves. unregisterParts(rem_list); //Clear the part variable. This should cause the last use of the shared pointer // to the part to be freed, therefore destroying the part. part.reset(); //Refresh all lists and maps refreshLists(); #ifdef _DEBUG printBodyMap("body_mt.gv", root.get()); #endif debug_print("done.\n"); }