// // EntityTypes.cpp // libraries/entities/src // // Created by Brad Hefta-Gaub on 12/4/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include #include #include #include "EntityItem.h" #include "EntityItemProperties.h" #include "EntityTypes.h" #include "BoxEntityItem.h" #include "LightEntityItem.h" #include "ModelEntityItem.h" #include "SphereEntityItem.h" #include "TextEntityItem.h" QMap EntityTypes::_typeToNameMap; QMap EntityTypes::_nameToTypeMap; EntityTypeFactory EntityTypes::_factories[EntityTypes::LAST + 1]; bool EntityTypes::_factoriesInitialized = false; const QString ENTITY_TYPE_NAME_UNKNOWN = "Unknown"; // Register Entity the default implementations of entity types here... REGISTER_ENTITY_TYPE(Model) REGISTER_ENTITY_TYPE(Box) REGISTER_ENTITY_TYPE(Sphere) REGISTER_ENTITY_TYPE(Light) REGISTER_ENTITY_TYPE(Text) const QString& EntityTypes::getEntityTypeName(EntityType entityType) { QMap::iterator matchedTypeName = _typeToNameMap.find(entityType); if (matchedTypeName != _typeToNameMap.end()) { return matchedTypeName.value(); } return ENTITY_TYPE_NAME_UNKNOWN; } EntityTypes::EntityType EntityTypes::getEntityTypeFromName(const QString& name) { QMap::iterator matchedTypeName = _nameToTypeMap.find(name); if (matchedTypeName != _nameToTypeMap.end()) { return matchedTypeName.value(); } return Unknown; } bool EntityTypes::registerEntityType(EntityType entityType, const char* name, EntityTypeFactory factoryMethod) { _typeToNameMap[entityType] = name; _nameToTypeMap[name] = entityType; if (!_factoriesInitialized) { memset(&_factories,0,sizeof(_factories)); _factoriesInitialized = true; } if (entityType >= 0 && entityType <= LAST) { _factories[entityType] = factoryMethod; return true; } return false; } EntityItem* EntityTypes::constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItem* newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { factory = _factories[entityType]; } if (factory) { // NOTE: if someone attempts to create an entity with properties that do not include a proper "created" time // then set the created time to now if (!properties.hasCreatedTime()) { EntityItemProperties mutableProperties = properties; mutableProperties.setCreated(usecTimestampNow()); newEntityItem = factory(entityID, mutableProperties); } else { newEntityItem = factory(entityID, properties); } } return newEntityItem; } EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead, ReadBitstreamToTreeParams& args) { if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) { EntityItemID tempEntityID; EntityItemProperties tempProperties; return constructEntityItem(Model, tempEntityID, tempProperties); } // Header bytes // object ID [16 bytes] // ByteCountCoded(type code) [~1 byte] // last edited [8 bytes] // ByteCountCoded(last_edited to last_updated delta) [~1-8 bytes] // PropertyFlags<>( everything ) [1-2 bytes] // ~27-35 bytes... const int MINIMUM_HEADER_BYTES = 27; int bytesRead = 0; if (bytesToRead >= MINIMUM_HEADER_BYTES) { int originalLength = bytesToRead; QByteArray originalDataBuffer((const char*)data, originalLength); // id QByteArray encodedID = originalDataBuffer.mid(bytesRead, NUM_BYTES_RFC4122_UUID); // maximum possible size QUuid actualID = QUuid::fromRfc4122(encodedID); bytesRead += encodedID.size(); // type QByteArray encodedType = originalDataBuffer.mid(bytesRead); // maximum possible size ByteCountCoded typeCoder = encodedType; encodedType = typeCoder; // determine true length bytesRead += encodedType.size(); quint32 type = typeCoder; EntityTypes::EntityType entityType = (EntityTypes::EntityType)type; EntityItemID tempEntityID(actualID); EntityItemProperties tempProperties; tempProperties.setCreated(usecTimestampNow()); // this is temporary... return constructEntityItem(entityType, tempEntityID, tempProperties); } return NULL; }