Exemple #1
0
/// 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;
                            }
                        }
                    }
                }
            }
        }
    }
}
Exemple #5
0
/// 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;
}