mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 18:56:55 +02:00
Working, but not cleaned up.
This commit is contained in:
parent
3f18e0cd09
commit
4a28dadae5
3 changed files with 92 additions and 43 deletions
|
@ -2791,18 +2791,18 @@ void Application::calibrateEyeTracker5Points() {
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
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;
|
QHash<EntityItemID, EntityDatum> entities;
|
||||||
|
|
||||||
auto entityTree = getEntities()->getTree();
|
auto entityTree = getEntities()->getTree();
|
||||||
|
@ -2818,13 +2818,15 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
||||||
}
|
}
|
||||||
|
|
||||||
auto properties = entityItem->getProperties();
|
auto properties = entityItem->getProperties();
|
||||||
auto position = properties.getPosition(); // see setPosition, below.
|
EntityItemID parentID = properties.getParentID();
|
||||||
root.x = glm::min(root.x, position.x);
|
if (parentID.isInvalidID() || !entityIDs.contains(parentID)) {
|
||||||
root.y = glm::min(root.y, position.y);
|
auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties.
|
||||||
root.z = glm::min(root.z, position.z);
|
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();
|
qCDebug(interfaceapp) << "Exporting" << entityItem->getEntityItemID() << entityItem->getName();
|
||||||
entities[entityID] = EntityDatum(entityItem, properties, properties.getParentID());
|
entities[entityID] = EntityDatum(entityItem, properties, parentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entities.size() == 0) {
|
if (entities.size() == 0) {
|
||||||
|
@ -2833,7 +2835,7 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
||||||
|
|
||||||
for (EntityDatum& entityDatum : entities) {
|
for (EntityDatum& entityDatum : entities) {
|
||||||
// Recursively add the parents of entities to the exportTree, mapping their new identifiers as we go.
|
// 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();
|
auto originalID = datum.item->getEntityItemID();
|
||||||
if (!datum.mappedID.isInvalidID()) {
|
if (!datum.mappedID.isInvalidID()) {
|
||||||
qCDebug(interfaceapp) << "already mapped" << datum.properties.getName() << originalID << "=>" << datum.mappedID;
|
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 properties = datum.properties;
|
||||||
auto parentID = datum.originalParentID;
|
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();
|
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]);
|
parentID = getMapped(entities[parentID]);
|
||||||
properties.setParentID(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?
|
datum.mappedID = originalID; // FIXME: simplify because we don't have to map ids.
|
||||||
// But leaving it in for bug-compatibility right now. -HRS
|
|
||||||
// FIXME properties.setPosition(properties.getPosition() - root);
|
|
||||||
datum.mappedID = originalID; //EntityItemID(QUuid::createUuid());
|
|
||||||
auto newEntity = exportTree->addEntity(datum.mappedID, properties);
|
auto newEntity = exportTree->addEntity(datum.mappedID, properties);
|
||||||
qCDebug(interfaceapp) << "mapped" << properties.getName();
|
qCDebug(interfaceapp) << "mapped" << properties.getName();
|
||||||
qCDebug(interfaceapp) << " " << originalID << "p:" << datum.originalParentID;
|
qCDebug(interfaceapp) << " " << originalID << "p:" << datum.originalParentID;
|
||||||
|
@ -2862,8 +2874,6 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
||||||
|
|
||||||
getMapped(entityDatum);
|
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());
|
exportTree->writeToJSONFile(filename.toLocal8Bit().constData());
|
||||||
|
|
||||||
|
|
|
@ -1320,26 +1320,62 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
|
||||||
float x, float y, float z) {
|
float x, float y, float z) {
|
||||||
SendEntitiesOperationArgs args;
|
SendEntitiesOperationArgs args;
|
||||||
args.packetSender = packetSender;
|
args.packetSender = packetSender;
|
||||||
args.localTree = localTree;
|
args.ourTree = this;
|
||||||
|
args.otherTree = localTree;
|
||||||
args.root = glm::vec3(x, y, z);
|
args.root = glm::vec3(x, y, z);
|
||||||
QVector<EntityItemID> newEntityIDs;
|
// If this is called repeatedly (e.g., multiple pastes with the same data), the new elements will clash unless we use new identifiers.
|
||||||
args.newEntityIDs = &newEntityIDs;
|
// We need to keep a map so that we can map parent identifiers correctly.
|
||||||
|
QHash<EntityItemID, EntityItemID> map;
|
||||||
|
args.map = ↦
|
||||||
recurseTreeWithOperation(sendEntitiesOperation, &args);
|
recurseTreeWithOperation(sendEntitiesOperation, &args);
|
||||||
packetSender->releaseQueuedMessages();
|
packetSender->releaseQueuedMessages();
|
||||||
|
|
||||||
return newEntityIDs;
|
return map.values().toVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extraData) {
|
bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extraData) {
|
||||||
qCDebug(entities) << "sendEntitiesOperation";
|
qCDebug(entities) << "sendEntitiesOperation";
|
||||||
SendEntitiesOperationArgs* args = static_cast<SendEntitiesOperationArgs*>(extraData);
|
SendEntitiesOperationArgs* args = static_cast<SendEntitiesOperationArgs*>(extraData);
|
||||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||||
entityTreeElement->forEachEntity([&](EntityItemPointer entityItem) {
|
std::function<const EntityItemID(EntityItemPointer&)> getMapped = [&](EntityItemPointer& item) -> const EntityItemID {
|
||||||
EntityItemID newID = /*entityItem->getEntityItemID(); // FIXME*/ (QUuid::createUuid());
|
EntityItemID oldID = item->getEntityItemID();
|
||||||
// FIXME: add map to SendEntitiesOperationArgs, and recurse through parent using the map
|
if (args->map->contains(oldID)) { // Already been handled (e.g., as a parent of somebody that we've processed).
|
||||||
args->newEntityIDs->append(newID);
|
return args->map->value(oldID);
|
||||||
EntityItemProperties properties = entityItem->getProperties();
|
}
|
||||||
//FIXME properties.setPosition(properties.getPosition() + args->root);
|
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
|
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();
|
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);
|
args->packetSender->queueEditEntityMessage(PacketType::EntityAdd, newID, properties);
|
||||||
|
|
||||||
// also update the local tree instantly (note: this is not our tree, but an alternate tree)
|
// 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->otherTree) {
|
||||||
if (args->localTree) {
|
args->otherTree->withWriteLock([&] {
|
||||||
args->localTree->withWriteLock([&] {
|
args->otherTree->addEntity(newID, properties);
|
||||||
args->localTree->addEntity(newID, properties);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
return newID;
|
||||||
|
};
|
||||||
|
|
||||||
|
entityTreeElement->forEachEntity(getMapped);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,10 @@ public:
|
||||||
class SendEntitiesOperationArgs {
|
class SendEntitiesOperationArgs {
|
||||||
public:
|
public:
|
||||||
glm::vec3 root;
|
glm::vec3 root;
|
||||||
EntityTreePointer localTree;
|
EntityTree* ourTree;
|
||||||
|
EntityTreePointer otherTree;
|
||||||
EntityEditPacketSender* packetSender;
|
EntityEditPacketSender* packetSender;
|
||||||
QVector<EntityItemID>* newEntityIDs;
|
QHash<EntityItemID, EntityItemID>* map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue