Пример #1
0
/// Tick the async loading of binary serialized data from the object cache for the given load request.
///
/// @param[in] pRequest  Load request.
///
/// @return  True if the cache load process has completed, false if it still requires processing.
bool CachePackageLoader::TickCacheLoad( LoadRequest* pRequest )
{
    HELIUM_ASSERT( pRequest );
    HELIUM_ASSERT( !( pRequest->flags & LOAD_FLAG_PRELOADED ) );

    AsyncLoader& rAsyncLoader = AsyncLoader::GetStaticInstance();

    size_t bytesRead = 0;
    if( !rAsyncLoader.TrySyncRequest( pRequest->asyncLoadId, bytesRead ) )
    {
        return false;
    }

    SetInvalid( pRequest->asyncLoadId );

    if( bytesRead == 0 || IsInvalid( bytesRead ) )
    {
        HELIUM_ASSERT( pRequest->pEntry );

        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "CachePackageLoader: Failed to read cache data for object \"%s\".\n" ),
            *pRequest->pEntry->path.ToString() );
    }
    else
    {
        uint8_t* pBufferEnd = pRequest->pAsyncLoadBuffer + bytesRead;
        pRequest->pPropertyStreamEnd = pBufferEnd;
        pRequest->pPersistentResourceStreamEnd = pBufferEnd;

        if( DeserializeLinkTables( pRequest ) )
        {
            return true;
        }
    }

    // An error occurred attempting to load the property data, so mark any existing object as fully loaded (nothing
    // else will be done with the object itself from here on out).
    DefaultAllocator().Free( pRequest->pAsyncLoadBuffer );
    pRequest->pAsyncLoadBuffer = NULL;

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

    pRequest->flags |= LOAD_FLAG_PRELOADED | LOAD_FLAG_ERROR;

    return true;
}
Пример #2
0
/// Update loading finalization for the given object load request.
///
/// @param[in] pRequest  Load request to update.
///
/// @return  True if load finalization has completed, false if not.
bool GameObjectLoader::TickFinalizeLoad( LoadRequest* pRequest )
{
    HELIUM_ASSERT( pRequest );

    GameObject* pObject = pRequest->spObject;
    if( pObject )
    {
        pObject->ConditionalFinalizeLoad();
    }

    // Loading now complete.
    OnLoadComplete( pRequest->path, pObject, pRequest->pPackageLoader );
    AtomicOrRelease( pRequest->stateFlags, LOAD_FLAG_LOADED );

    return true;
}
Пример #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;
}