Ejemplo n.º 1
0
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
GameObjectType::pDocument_type
GameObjectType::getDocument()
{
    if (m_pDocument.isValid())
    {
        return m_pDocument;
    }

    // Create a document and return it.

    // Get a reference to the workbench
    Zen::Studio::Workbench::I_WorkbenchService& 
        workbench(m_project.getController().getWorkbenchService());

    // TODO Create a spread sheet document user data.
    // Since GameObjectTypeDocument is a user-implemented document,
    // the user data isn't needed, but possibly eventually it will be.
    //Zen::Studio::Workbench::I_SpreadSheetDocument::pUserData_type
    //    pUserData();

    // Get the parent document.
    Zen::Studio::Workbench::I_ExplorerNode* const pParentNode = getNode()->getParent();

    pDocument_type* ppParentDocument = NULL;

    // If the parent node isn't NULL, see if the user data is a GameObjectType
    if (pParentNode != NULL)
    {
        GameObjectType* pParent = dynamic_cast<GameObjectType*>(pParentNode->getUserData().get());

        if (pParent)
        {
            ppParentDocument = new pDocument_type(pParent->getDocument());
        }
    }

    // Create the document.
    GameObjectTypeDocument* pRawDocument = new GameObjectTypeDocument(m_project, ppParentDocument);
    Zen::Studio::Workbench::I_Document::pDocument_type 
        pGameObjectTypeDocument(pRawDocument, &GameObjectType::destroyDocument);

    // TODO Create a future and pass it to this method.  Then have
    // this method fire the future event when the document is fully loaded.
    pRawDocument->load(*this);

    m_pDocument = pGameObjectTypeDocument;

    onOpened(pRawDocument);

    // TODO Return a future.
    return m_pDocument;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/// Tick the object deserialization process for the given object load request.
///
/// @param[in] pRequest  Load request.
///
/// @return  True if the deserialization process has completed, false if it still needs time to process.
bool CachePackageLoader::TickDeserialize( LoadRequest* pRequest )
{
    HELIUM_ASSERT( pRequest );
    HELIUM_ASSERT( !( pRequest->flags & LOAD_FLAG_PRELOADED ) );

    GameObject* pObject = pRequest->spObject;

    const Cache::Entry* pCacheEntry = pRequest->pEntry;
    HELIUM_ASSERT( pCacheEntry );

    // Wait for the template and owner objects to load.
    GameObjectLoader* pObjectLoader = GameObjectLoader::GetStaticInstance();
    HELIUM_ASSERT( pObjectLoader );

    if( IsValid( pRequest->templateLinkIndex ) )
    {
        HELIUM_ASSERT( pRequest->templateLinkIndex < pRequest->objectLinkTable.GetSize() );
        size_t templateLoadId = pRequest->objectLinkTable[ pRequest->templateLinkIndex ];
        if( IsValid( templateLoadId ) && !pObjectLoader->TryFinishLoad( templateLoadId, pRequest->spTemplate ) )
        {
            return false;
        }

        SetInvalid( pRequest->templateLinkIndex );

        if( !pRequest->spTemplate )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "CachePackageLoader: Failed to load template object for \"%s\".\n" ),
                *pCacheEntry->path.ToString() );

            if( pObject )
            {
                pObject->SetFlags( GameObject::FLAG_PRELOADED | GameObject::FLAG_LINKED );
                pObject->ConditionalFinalizeLoad();
            }

            DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
            pRequest->pAsyncLoadBuffer = NULL;

            pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

            return true;
        }
    }

    GameObject* pTemplate = pRequest->spTemplate;

    if( IsValid( pRequest->ownerLinkIndex ) )
    {
        HELIUM_ASSERT( pRequest->ownerLinkIndex < pRequest->objectLinkTable.GetSize() );
        size_t ownerLoadId = pRequest->objectLinkTable[ pRequest->ownerLinkIndex ];
        if( IsValid( ownerLoadId ) && !pObjectLoader->TryFinishLoad( ownerLoadId, pRequest->spOwner ) )
        {
            return false;
        }

        SetInvalid( pRequest->ownerLinkIndex );

        if( !pRequest->spOwner )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "CachePackageLoader: Failed to load owner object for \"%s\".\n" ),
                *pCacheEntry->path.ToString() );

            if( pObject )
            {
                pObject->SetFlags( GameObject::FLAG_PRELOADED | GameObject::FLAG_LINKED );
                pObject->ConditionalFinalizeLoad();
            }

            DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
            pRequest->pAsyncLoadBuffer = NULL;

            pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

            return true;
        }
    }

    GameObject* pOwner = pRequest->spOwner;

    HELIUM_ASSERT( !pOwner || pOwner->IsFullyLoaded() );
    HELIUM_ASSERT( !pTemplate || pTemplate->IsFullyLoaded() );

    GameObjectType* pType = pRequest->spType;
    HELIUM_ASSERT( pType );

    // If we already had an existing object, make sure the type and template match.
    if( pObject )
    {
        const GameObjectType* pExistingType = pObject->GetGameObjectType();
        HELIUM_ASSERT( pExistingType );
        if( pExistingType != pType )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                ( TXT( "CachePackageLoader: Cannot load \"%s\" using the existing object as the types do not " )
                TXT( "match (existing type: \"%s\"; serialized type: \"%s\".\n" ) ),
                *pCacheEntry->path.ToString(),
                *pExistingType->GetName(),
                *pType->GetName() );

            pObject->SetFlags( GameObject::FLAG_PRELOADED | GameObject::FLAG_LINKED );
            pObject->ConditionalFinalizeLoad();

            DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
            pRequest->pAsyncLoadBuffer = NULL;

            pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

            return true;
        }
    }
    else
    {
        // Create the object.
        if( !GameObject::CreateObject( pRequest->spObject, pType, pCacheEntry->path.GetName(), pOwner, pTemplate ) )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "CachePackageLoader: Failed to create \"%s\" during loading.\n" ),
                *pCacheEntry->path.ToString() );

            DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
            pRequest->pAsyncLoadBuffer = NULL;

            pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

            return true;
        }

        pObject = pRequest->spObject;
        HELIUM_ASSERT( pObject );
    }
        
    Reflect::ObjectPtr cached_object = Cache::ReadCacheObjectFromBuffer(pRequest->pSerializedData, 0, pRequest->pPropertyStreamEnd - pRequest->pSerializedData);

    if (!cached_object.ReferencesObject())
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "CachePackageLoader: Failed to deserialize object \"%s\".\n" ),
            *pCacheEntry->path.ToString() );

        // Clear out object references (object can now be considered fully loaded as well).
        // pmd - Not sure that we need to do this.. but if we do, just use this visitor
        //ClearLinkIndicesFromObject clifo_visitor;
        //pObject->Accept(clifo_visitor);
        pObject->SetFlags( GameObject::FLAG_LINKED );
        pObject->ConditionalFinalizeLoad();

        pRequest->flags |= LOAD_FLAG_ERROR;
    }
    else
    {
        cached_object->CopyTo(pObject);
                
        if( !pObject->IsDefaultTemplate() )
        {
            // Load persistent resource data.
            Resource* pResource = Reflect::SafeCast< Resource >( pObject );
            if( pResource )
            {
                Reflect::ObjectPtr cached_prd = Cache::ReadCacheObjectFromBuffer(
                    pRequest->pPropertyStreamEnd, 
                    0, 
                    (pRequest->pPersistentResourceStreamEnd - pRequest->pPropertyStreamEnd));

                if (!cached_prd.ReferencesObject())
                {
                    HELIUM_TRACE(
                        TraceLevels::Error,
                        ( TXT( "CachePackageLoader: Failed to deserialize persistent resource " )
                        TXT( "data for \"%s\".\n" ) ),
                        *pCacheEntry->path.ToString() );
                }
                else
                {
                    pResource->LoadPersistentResourceObject(cached_prd);
                }
            }
        }
    }

    DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
    pRequest->pAsyncLoadBuffer = NULL;

    pObject->SetFlags( GameObject::FLAG_PRELOADED );

    pRequest->flags |= LOAD_FLAG_PRELOADED;

    // GameObject is now preloaded.
    return true;
}