/// Unregister a type. /// /// Note that this should only be called by the static type release functions (i.e. Entity::ReleaseStaticType()). /// /// @param[in] pType Type to unregister. References to the parent type and the type template will be released as well. /// /// @see Register() void GameObjectType::Unregister( const GameObjectType* pType ) { HELIUM_ASSERT( pType ); // Unregister all child types first. const Composite* pDerived = pType->m_FirstDerived; while( pDerived ) { HELIUM_ASSERT( pDerived->GetReflectionType() == Reflect::ReflectionTypes::GameObjectType ); const GameObjectType* pDerivedGameObjectType = static_cast< const GameObjectType* >( pDerived ); const Composite* pNextDerived = pDerived->m_NextSibling; RELEASE_STATIC_TYPE_CALLBACK* pReleaseStaticType = pDerivedGameObjectType->m_pReleaseStaticTypeCallback; HELIUM_ASSERT( pReleaseStaticType ); pReleaseStaticType(); pDerived = pNextDerived; } // Remove this type from all type registries. Reflect::Registry* pRegistry = Reflect::Registry::GetInstance(); HELIUM_ASSERT( pRegistry ); pRegistry->UnregisterType( pType ); HELIUM_ASSERT( sm_pLookupMap ); HELIUM_VERIFY( sm_pLookupMap->Remove( pType->GetName() ) ); }
const ComponentPtr& ComponentCollection::GetComponent(i32 slotID) const { static const ComponentPtr kNull; const M_Component::const_iterator end = m_Components.end(); M_Component::const_iterator found = m_Components.find( slotID ); if ( found != end ) { return found->second; } else { // Travel up the inheritance hierarchy looking for a base class slot within // this collection. Reflect::Registry* registry = Reflect::Registry::GetInstance(); const Reflect::Class* type = registry->GetClass( slotID ); type = registry->GetInstance()->GetClass( type->m_Base ); // While we have base class type information, and we haven't hit the Component // base class, keep iterating. while ( type && ( type->m_TypeID != Reflect::GetType< ComponentBase >() ) ) { // See if the base class has a slot in this collection. found = m_Components.find( type->m_TypeID ); if ( found != end ) { return found->second; } type = registry->GetInstance()->GetClass( type->m_Base ); } } return kNull; }
void ComponentCollection::CopyTo(const Reflect::ElementPtr& destination) { __super::CopyTo( destination ); ComponentCollection* destCollection = Reflect::ObjectCast< ComponentCollection >( destination ); if ( destCollection ) { // Remove all attributes, we're going to bring them over manually destCollection->Clear(); // For each component in this component collection Reflect::Registry* registry = Reflect::Registry::GetInstance(); M_Component::const_iterator attrItr = m_Components.begin(); M_Component::const_iterator attrEnd = m_Components.end(); for ( ; attrItr != attrEnd; ++attrItr ) { // Create a new copy of the component and try to add it to the destination const ComponentPtr& attrib = attrItr->second; ComponentPtr destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( attrib->GetClass() ) ); if ( !CopyComponentTo( *destCollection, destAttrib, attrib ) ) { // Component could not be added to the destination collection, check sibling classes const std::set<tstring>& derived = ( registry->GetClass( attrib->GetClass()->m_Base ) )->m_Derived; std::set<tstring>::const_iterator derivedItr = derived.begin(); std::set<tstring>::const_iterator derivedEnd = derived.end(); for ( ; derivedItr != derivedEnd; ++derivedItr ) { const Reflect::Class* currentType = Reflect::Registry::GetInstance()->GetClass(*derivedItr); if ( currentType->m_TypeID != attrib->GetType() ) { destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( currentType ) ); if ( destAttrib.ReferencesObject() ) { if ( CopyComponentTo( *destCollection, destAttrib, attrib ) ) { break; } } } } } } } }
void ComponentCollection::CopyTo(Reflect::Object* object) { Base::CopyTo( object ); ComponentCollection* collection = Reflect::SafeCast< ComponentCollection >( object ); if ( collection ) { // Remove all attributes, we're going to bring them over manually collection->Clear(); // For each component in this component collection Reflect::Registry* registry = Reflect::Registry::GetInstance(); M_Component::const_iterator attrItr = m_Components.begin(); M_Component::const_iterator attrEnd = m_Components.end(); for ( ; attrItr != attrEnd; ++attrItr ) { // Create a new copy of the component and try to add it to the destination const ComponentPtr& attrib = attrItr->second; ComponentPtr destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( attrib->GetMetaClass() ) ); if ( !CopyComponentTo( *collection, destAttrib, attrib ) ) { // Component could not be added to the destination collection, check sibling classes for ( const Composite* sibling = attrib->GetMetaClass()->m_Base->m_FirstDerived; sibling; sibling = sibling->m_NextSibling ) { if ( sibling != attrib->GetMetaClass() ) { destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( Reflect::ReflectionCast< const MetaClass >( sibling ) ) ); if ( destAttrib.ReferencesObject() ) { if ( CopyComponentTo( *collection, destAttrib, attrib ) ) { break; } } } } } } } }
/// Create a type object. /// /// @param[in] name Type name. /// @param[in] pTypePackage Package in which the template object should be stored. /// @param[in] pParent Parent type. /// @param[in] pTemplate Template object. /// @param[in] flags Type flags. /// /// @return Pointer to the type object if created successfully, null if not. /// /// @see Unregister() const GameObjectType* GameObjectType::Create( Name name, Package* pTypePackage, const GameObjectType* pParent, GameObject* pTemplate, RELEASE_STATIC_TYPE_CALLBACK* pReleaseStaticTypeCallback, uint32_t flags ) { HELIUM_ASSERT( !name.IsEmpty() ); HELIUM_ASSERT( pTypePackage ); HELIUM_ASSERT( pTemplate ); HELIUM_ASSERT( pReleaseStaticTypeCallback ); // Register the template object with the object system. if( !GameObject::RegisterObject( pTemplate ) ) { HELIUM_TRACE( TRACE_ERROR, TXT( "GameObjectType::Initialize(): Failed to register type \"%s\" template object.\n" ), *name ); return false; } // Set up the template object name, and set this object as its parent. GameObject::RenameParameters nameParameters; nameParameters.name = name; nameParameters.spOwner = pTypePackage; if( !pTemplate->Rename( nameParameters ) ) { HELIUM_TRACE( TRACE_ERROR, TXT( "GameObjectType::Initialize(): Failed to set type \"%s\" template object name and owner.\n" ), *name ); GameObject::UnregisterObject( pTemplate ); return false; } // Flag the object as the default template object for the type being created. pTemplate->SetFlags( GameObject::FLAG_DEFAULT_TEMPLATE ); // If the parent type is null, default to Reflect::Object, as the type should be deriving from it directly. const Reflect::Class* pBaseClass = pParent; if( !pBaseClass ) { pBaseClass = Reflect::Object::s_Class; HELIUM_ASSERT( pBaseClass ); } // Create the type object and store its parameters. GameObjectType* pType = new GameObjectType; HELIUM_ASSERT( pType ); pType->m_Name = *name; pType->m_Size = static_cast< uint32_t >( pTemplate->GetInstanceSize() ); pType->m_Base = pBaseClass; pType->Composite::m_Default = pType->m_Default = pTemplate; pType->m_cachedName = name; pType->m_pReleaseStaticTypeCallback = pReleaseStaticTypeCallback; pType->m_flags = flags; if( pParent ) { pParent->AddDerived( pType ); } // Lazily initialize the lookup map. Note that this is not inherently thread-safe, but there should always be // at least one type registered before any sub-threads are spawned. if( !sm_pLookupMap ) { sm_pLookupMap = new LookupMap; HELIUM_ASSERT( sm_pLookupMap ); } // Register the type (note that a type with the same name should not already exist in the lookup map). LookupMap::Iterator typeIterator; HELIUM_VERIFY( sm_pLookupMap->Insert( typeIterator, KeyValue< Name, GameObjectTypePtr >( pType->GetName(), pType ) ) ); Reflect::Registry* pRegistry = Reflect::Registry::GetInstance(); HELIUM_ASSERT( pRegistry ); pRegistry->RegisterType( pType ); return pType; }