QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties) { EntityItemProperties propertiesWithSimID = properties; EntityItemID id = EntityItemID(QUuid::createUuid()); // If we have a local entity tree set, then also update it. bool success = true; if (_entityTree) { _entityTree->withWriteLock([&] { EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); if (entity) { // This Node is creating a new object. If it's in motion, set this Node as the simulator. auto nodeList = DependencyManager::get<NodeList>(); const QUuid myNodeID = nodeList->getSessionUUID(); propertiesWithSimID.setSimulationOwner(myNodeID, SCRIPT_EDIT_SIMULATION_PRIORITY); // and make note of it now, so we can act on it right away. entity->setSimulationOwner(myNodeID, SCRIPT_EDIT_SIMULATION_PRIORITY); entity->setLastBroadcast(usecTimestampNow()); } else { qCDebug(entities) << "script failed to add new Entity to local Octree"; success = false; } }); } // queue the packet if (success) { queueEntityMessage(PacketType::EntityAdd, id, propertiesWithSimID); } return id; }
int main(int argc, char** argv) { QCoreApplication app(argc, argv); { auto start = usecTimestampNow(); for (int i = 0; i < 1000; ++i) { testPropertyFlags(); testByteCountCoded<quint8>(); testByteCountCoded<quint16>(); testByteCountCoded<quint32>(); testByteCountCoded<quint64>(); } auto duration = usecTimestampNow() - start; qDebug() << duration; } DependencyManager::set<NodeList>(NodeType::Unassigned); QFile file(getTestResourceDir() + "packet.bin"); if (!file.open(QIODevice::ReadOnly)) return -1; QByteArray packet = file.readAll(); EntityItemPointer item = BoxEntityItem::factory(EntityItemID(), EntityItemProperties()); ReadBitstreamToTreeParams params; params.bitstreamVersion = 33; auto start = usecTimestampNow(); for (int i = 0; i < 1000; ++i) { item->readEntityDataFromBuffer(reinterpret_cast<const unsigned char*>(packet.constData()), packet.size(), params); } float duration = (usecTimestampNow() - start); qDebug() << (duration / 1000.0f); return 0; }
EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) { EntityItemProperties results; if (_entityTree) { _entityTree->withReadLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); if (entity) { results = entity->getProperties(desiredProperties); // TODO: improve sitting points and naturalDimensions in the future, // for now we've included the old sitting points model behavior for entity types that are models // we've also added this hack for setting natural dimensions of models if (entity->getType() == EntityTypes::Model) { const FBXGeometry* geometry = _entityTree->getGeometryForEntity(entity); if (geometry) { results.setSittingPoints(geometry->sittingPoints); Extents meshExtents = geometry->getUnscaledMeshExtents(); results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); results.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); } } } }); } return results; }
QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties) { EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties); propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); auto dimensions = propertiesWithSimID.getDimensions(); float volume = dimensions.x * dimensions.y * dimensions.z; auto density = propertiesWithSimID.getDensity(); auto newVelocity = propertiesWithSimID.getVelocity().length(); float cost = calculateCost(density * volume, 0, newVelocity); cost *= costMultiplier; if (cost > _currentAvatarEnergy) { return QUuid(); } EntityItemID id = EntityItemID(QUuid::createUuid()); // If we have a local entity tree set, then also update it. bool success = true; if (_entityTree) { _entityTree->withWriteLock([&] { EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); if (entity) { if (propertiesWithSimID.parentRelatedPropertyChanged()) { // due to parenting, the server may not know where something is in world-space, so include the bounding cube. bool success; AACube queryAACube = entity->getQueryAACube(success); if (success) { propertiesWithSimID.setQueryAACube(queryAACube); } } if (_bidOnSimulationOwnership) { // This Node is creating a new object. If it's in motion, set this Node as the simulator. auto nodeList = DependencyManager::get<NodeList>(); const QUuid myNodeID = nodeList->getSessionUUID(); // and make note of it now, so we can act on it right away. propertiesWithSimID.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); entity->setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); } entity->setLastBroadcast(usecTimestampNow()); } else { qCDebug(entities) << "script failed to add new Entity to local Octree"; success = false; } }); } // queue the packet if (success) { emit debitEnergySource(cost); queueEntityMessage(PacketType::EntityAdd, id, propertiesWithSimID); } return id; }
void addAvatarEntities(const QVariantList& avatarEntities) { auto nodeList = DependencyManager::get<NodeList>(); const QUuid myNodeID = nodeList->getSessionUUID(); EntityTreePointer entityTree = DependencyManager::get<EntityTreeRenderer>()->getTree(); if (!entityTree) { return; } EntitySimulationPointer entitySimulation = entityTree->getSimulation(); PhysicalEntitySimulationPointer physicalEntitySimulation = std::static_pointer_cast<PhysicalEntitySimulation>(entitySimulation); EntityEditPacketSender* entityPacketSender = physicalEntitySimulation->getPacketSender(); QScriptEngine scriptEngine; for (int index = 0; index < avatarEntities.count(); index++) { const QVariantMap& avatarEntityProperties = avatarEntities.at(index).toMap(); QVariant variantProperties = avatarEntityProperties["properties"]; QVariantMap asMap = variantProperties.toMap(); QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); EntityItemProperties entityProperties; EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties); entityProperties.setParentID(myNodeID); entityProperties.setClientOnly(true); entityProperties.setOwningAvatarID(myNodeID); entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY); entityProperties.markAllChanged(); EntityItemID id = EntityItemID(QUuid::createUuid()); bool success = true; entityTree->withWriteLock([&] { EntityItemPointer entity = entityTree->addEntity(id, entityProperties); if (entity) { if (entityProperties.queryAACubeRelatedPropertyChanged()) { // due to parenting, the server may not know where something is in world-space, so include the bounding cube. bool success; AACube queryAACube = entity->getQueryAACube(success); if (success) { entityProperties.setQueryAACube(queryAACube); } } entity->setLastBroadcast(usecTimestampNow()); // since we're creating this object we will immediately volunteer to own its simulation entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); entityProperties.setLastEdited(entity->getLastEdited()); } else { qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree"; success = false; } }); if (success) { entityPacketSender->queueEditEntityMessage(PacketType::EntityAdd, entityTree, id, entityProperties); } } }
void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { bool wantEditLogging = false; readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging); qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging)); bool wantTerseEditLogging = false; readOptionBool(QString("wantTerseEditLogging"), settingsSectionObject, wantTerseEditLogging); qDebug("wantTerseEditLogging=%s", debug::valueOf(wantTerseEditLogging)); EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree); int maxTmpEntityLifetime; if (readOptionInt("maxTmpLifetime", settingsSectionObject, maxTmpEntityLifetime)) { tree->setEntityMaxTmpLifetime(maxTmpEntityLifetime); } else { tree->setEntityMaxTmpLifetime(EntityTree::DEFAULT_MAX_TMP_ENTITY_LIFETIME); } int minTime; if (readOptionInt("dynamicDomainVerificationTimeMin", settingsSectionObject, minTime)) { _MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = minTime * 1000; } int maxTime; if (readOptionInt("dynamicDomainVerificationTimeMax", settingsSectionObject, maxTime)) { _MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = maxTime * 1000; } startDynamicDomainVerification(); tree->setWantEditLogging(wantEditLogging); tree->setWantTerseEditLogging(wantTerseEditLogging); QString entityScriptSourceWhitelist; if (readOptionString("entityScriptSourceWhitelist", settingsSectionObject, entityScriptSourceWhitelist)) { tree->setEntityScriptSourceWhitelist(entityScriptSourceWhitelist); } else { tree->setEntityScriptSourceWhitelist(""); } auto entityEditFilters = DependencyManager::get<EntityEditFilters>(); QString filterURL; if (readOptionString("entityEditFilter", settingsSectionObject, filterURL) && !filterURL.isEmpty()) { // connect the filterAdded signal, and block edits until you hear back connect(entityEditFilters.data(), &EntityEditFilters::filterAdded, this, &EntityServer::entityFilterAdded); entityEditFilters->addFilter(EntityItemID(), filterURL); } }
EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) { EntityItemProperties results; if (_entityTree) { _entityTree->withReadLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); if (entity) { if (desiredProperties.getHasProperty(PROP_POSITION) || desiredProperties.getHasProperty(PROP_ROTATION) || desiredProperties.getHasProperty(PROP_LOCAL_POSITION) || desiredProperties.getHasProperty(PROP_LOCAL_ROTATION)) { // if we are explicitly getting position or rotation, we need parent information to make sense of them. desiredProperties.setHasProperty(PROP_PARENT_ID); desiredProperties.setHasProperty(PROP_PARENT_JOINT_INDEX); } if (desiredProperties.isEmpty()) { // these are left out of EntityItem::getEntityProperties so that localPosition and localRotation // don't end up in json saves, etc. We still want them here, though. EncodeBitstreamParams params; // unknown desiredProperties = entity->getEntityProperties(params); desiredProperties.setHasProperty(PROP_LOCAL_POSITION); desiredProperties.setHasProperty(PROP_LOCAL_ROTATION); } results = entity->getProperties(desiredProperties); // TODO: improve sitting points and naturalDimensions in the future, // for now we've included the old sitting points model behavior for entity types that are models // we've also added this hack for setting natural dimensions of models if (entity->getType() == EntityTypes::Model) { const FBXGeometry* geometry = _entityTree->getGeometryForEntity(entity); if (geometry) { results.setSittingPoints(geometry->sittingPoints); Extents meshExtents = geometry->getUnscaledMeshExtents(); results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); results.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); } } } }); } return convertLocationToScriptSemantics(results); }
EntityItemID EntityItemID::getIDfromCreatorTokenID(uint32_t creatorTokenID) { if (_tokenIDsToIDs.find(creatorTokenID) != _tokenIDsToIDs.end()) { return EntityItemID(_tokenIDsToIDs[creatorTokenID], creatorTokenID, true); } return EntityItemID(UNKNOWN_ENTITY_ID); }