Working, but not cleaned up.

This commit is contained in:
howard-stearns 2016-03-29 13:26:50 -07:00
parent 3f18e0cd09
commit 4a28dadae5
3 changed files with 92 additions and 43 deletions

View file

@ -2791,18 +2791,18 @@ void Application::calibrateEyeTracker5Points() {
}
#endif
class EntityDatum { // For parent-first sorting and mapping.
public:
EntityItemPointer item;
EntityItemProperties properties;
EntityItemID originalParentID;
EntityItemID mappedID;
EntityDatum() {};
EntityDatum(EntityItemPointer itemArg, EntityItemProperties propertiesArg, EntityItemID parentID) :
item(itemArg), properties(propertiesArg), originalParentID(parentID) {
};
};
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
class EntityDatum { // For parent-first sorting and mapping.
public:
EntityItemPointer item;
EntityItemProperties properties;
EntityItemID originalParentID;
EntityItemID mappedID;
EntityDatum() {};
EntityDatum(EntityItemPointer itemArg, EntityItemProperties propertiesArg, EntityItemID parentID) :
item(itemArg), properties(propertiesArg), originalParentID(parentID) {
};
};
QHash<EntityItemID, EntityDatum> entities;
auto entityTree = getEntities()->getTree();
@ -2818,13 +2818,15 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
}
auto properties = entityItem->getProperties();
auto position = properties.getPosition(); // see setPosition, below.
root.x = glm::min(root.x, position.x);
root.y = glm::min(root.y, position.y);
root.z = glm::min(root.z, position.z);
EntityItemID parentID = properties.getParentID();
if (parentID.isInvalidID() || !entityIDs.contains(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);
}
qCDebug(interfaceapp) << "Exporting" << entityItem->getEntityItemID() << entityItem->getName();
entities[entityID] = EntityDatum(entityItem, properties, properties.getParentID());
entities[entityID] = EntityDatum(entityItem, properties, parentID);
}
if (entities.size() == 0) {
@ -2833,7 +2835,7 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
for (EntityDatum& entityDatum : entities) {
// Recursively add the parents of entities to the exportTree, mapping their new identifiers as we go.
std::function<EntityItemID(EntityDatum&)> getMapped = [&](EntityDatum& datum) {
std::function<EntityItemID(EntityDatum&)> getMapped = [&](EntityDatum& datum) { // FIXME: move definition outside the loop
auto originalID = datum.item->getEntityItemID();
if (!datum.mappedID.isInvalidID()) {
qCDebug(interfaceapp) << "already mapped" << datum.properties.getName() << originalID << "=>" << datum.mappedID;
@ -2841,16 +2843,26 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
}
auto properties = datum.properties;
auto parentID = datum.originalParentID;
if (!datum.originalParentID.isInvalidID()) { // Recurse over ancestors, updating properties.
if (parentID.isInvalidID() || !entityIDs.contains(parentID)) {
bool success;
auto globalPosition = datum.item->getPosition(success);
if (success) {
properties.setPosition(globalPosition - root);
if (!parentID.isInvalidID()) { // There's a parent that we won't output. Make the other data global.
properties.setRotation(datum.item->getRotation());
properties.setDimensions(datum.item->getDimensions());
// Should we do velocities and accelerations, too?
}
} else {
properties.setPosition(datum.item->getQueryAACube().calcCenter() - root); // best we can do
}
} else {// Recurse over ancestors, updating properties.
qCDebug(interfaceapp) << "FIXME recursing" << datum.originalParentID << "parent of" << datum.item->getEntityItemID();
// Warning: this is not a tail-call, so exporting a REALLY deep parent hierarchy will blow the call stack.
// Warning: could blow the call stack if the parent hierarchy is VERY deep.
parentID = getMapped(entities[parentID]);
properties.setParentID(parentID);
}
// The so-called root offset (which isn't) is confusing and not what content developers want. And why would queryAACube not then be offset?
// But leaving it in for bug-compatibility right now. -HRS
// FIXME properties.setPosition(properties.getPosition() - root);
datum.mappedID = originalID; //EntityItemID(QUuid::createUuid());
datum.mappedID = originalID; // FIXME: simplify because we don't have to map ids.
auto newEntity = exportTree->addEntity(datum.mappedID, properties);
qCDebug(interfaceapp) << "mapped" << properties.getName();
qCDebug(interfaceapp) << " " << originalID << "p:" << datum.originalParentID;
@ -2862,8 +2874,6 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
getMapped(entityDatum);
}
// remap IDs on export so that we aren't publishing the IDs of entities in our domain
//exportTree->remapIDs();
exportTree->writeToJSONFile(filename.toLocal8Bit().constData());

View file

@ -1320,26 +1320,62 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
float x, float y, float z) {
SendEntitiesOperationArgs args;
args.packetSender = packetSender;
args.localTree = localTree;
args.ourTree = this;
args.otherTree = localTree;
args.root = glm::vec3(x, y, z);
QVector<EntityItemID> newEntityIDs;
args.newEntityIDs = &newEntityIDs;
// If this is called repeatedly (e.g., multiple pastes with the same data), the new elements will clash unless we use new identifiers.
// We need to keep a map so that we can map parent identifiers correctly.
QHash<EntityItemID, EntityItemID> map;
args.map = &map;
recurseTreeWithOperation(sendEntitiesOperation, &args);
packetSender->releaseQueuedMessages();
return newEntityIDs;
return map.values().toVector();
}
bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extraData) {
qCDebug(entities) << "sendEntitiesOperation";
SendEntitiesOperationArgs* args = static_cast<SendEntitiesOperationArgs*>(extraData);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->forEachEntity([&](EntityItemPointer entityItem) {
EntityItemID newID = /*entityItem->getEntityItemID(); // FIXME*/ (QUuid::createUuid());
// FIXME: add map to SendEntitiesOperationArgs, and recurse through parent using the map
args->newEntityIDs->append(newID);
EntityItemProperties properties = entityItem->getProperties();
//FIXME properties.setPosition(properties.getPosition() + args->root);
std::function<const EntityItemID(EntityItemPointer&)> getMapped = [&](EntityItemPointer& item) -> const EntityItemID {
EntityItemID oldID = item->getEntityItemID();
if (args->map->contains(oldID)) { // Already been handled (e.g., as a parent of somebody that we've processed).
return args->map->value(oldID);
}
EntityItemID newID = QUuid::createUuid();
args->map->insert(oldID, newID);
EntityItemProperties properties = item->getProperties();
EntityItemID oldParentID = properties.getParentID();
if (oldParentID.isInvalidID()) { // no parent
properties.setPosition(properties.getPosition() + args->root);
} else {
EntityItemPointer parentEntity = args->ourTree->findEntityByEntityItemID(oldParentID);
if (parentEntity) { // map the parent
// Warning: could blow the call stack if the parent hierarchy is VERY deep.
properties.setParentID(getMapped(parentEntity));
// But do not add root offset in this case.
} else { // Should not happen, but let's try to be helpful...
// Log what we can.
QString name = properties.getName();
if (name.isEmpty()) {
name = EntityTypes::getEntityTypeName(properties.getType());
}
bool success;
glm::vec3 position = item->getPosition(success);
qCWarning(entities) << "Cannot find" << oldParentID << "parent of" << oldID << name << (success ? "" : "and unable to resolve geometry");
// Adjust geometry with absolute/global values.
if (success) {
properties.setPosition(position + args->root);
properties.setRotation(item->getRotation());
properties.setDimensions(item->getDimensions());
// Should we do velocities and accelerations, too?
} else {
properties.setPosition(item->getQueryAACube().calcCenter() + args->root); // best we can do
}
QUuid empty;
properties.setParentID(empty);
}
}
properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity
qCDebug(entities) << "sending" << newID << properties.getName() << "parent:" << properties.getParentID() << "pos:" << properties.getPosition();
@ -1347,13 +1383,15 @@ bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extra
args->packetSender->queueEditEntityMessage(PacketType::EntityAdd, newID, properties);
// also update the local tree instantly (note: this is not our tree, but an alternate tree)
// [Sure looks like the global application's tree to me. See callers. -HRS]
if (args->localTree) {
args->localTree->withWriteLock([&] {
args->localTree->addEntity(newID, properties);
if (args->otherTree) {
args->otherTree->withWriteLock([&] {
args->otherTree->addEntity(newID, properties);
});
}
});
return newID;
};
entityTreeElement->forEachEntity(getMapped);
return true;
}

View file

@ -47,9 +47,10 @@ public:
class SendEntitiesOperationArgs {
public:
glm::vec3 root;
EntityTreePointer localTree;
EntityTree* ourTree;
EntityTreePointer otherTree;
EntityEditPacketSender* packetSender;
QVector<EntityItemID>* newEntityIDs;
QHash<EntityItemID, EntityItemID>* map;
};