示例#1
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;
}