sources/BoxMooV_Texture.c

/*
 *  BoxMooV_Texture.c
 *
 *  Rick Evans Sept. 1996                           
 *  Robert Dierkes                                                                              
 *  (c)1994-96 Apple Computer Inc., All Rights Reserved                             
 *  
*/
 
/*------------------*/
/*  Include Files   */
/*------------------*/
#include <QuickDraw.h>
#include <Resources.h>
 
#include "QD3D.h"
#include "QD3DGroup.h"
#include "QD3DShader.h"
#include "QD3DSet.h"
 
#include "BoxMooV_Texture.h"
#include "BoxMooV_QuickTime.h"
 
/*--------------------------*/
/*    Private prototypes    */
/*--------------------------*/
 
TQ3Status   AddTextureToGroup(TQ3GroupObject group, TQ3StoragePixmap *pStoragePixmap);
 
/*--------------*/
/*  Routines    */
/*--------------*/
 
/*===========================================================================*\
 *
 *  Routine:    Texture_New()
 *
 *  Comments:   Create a new Animated Texture
 *              Set its fMovie field to a new Movie provided by user.
 *              Create a new GWorld with dimension based on the Moive's bounds.
 *              Set the Movie to draw into the GWorld.
 *              Create a new Storage Pixmap based on the GWorld
 *              Start movie playing in a loop.
 *
\*===========================================================================*/
 
TAnimatedTextureHdl Texture_New(
            void)
{
    unsigned long       pictMapAddr;
    GWorldPtr           pGWorld;
    PixMapHandle        hPixMap;
    unsigned long       pictRowBytes;
    QDErr               err;
    GDHandle            oldGD;
    GWorldPtr           oldGW;
    Boolean             success;
    Rect                bounds;
    TQ3StoragePixmap    *strgPMap;
    TAnimatedTextureHdl theAnimTxtr = (TAnimatedTextureHdl)NewHandleClear(sizeof(TAnimatedTexture));
 
    HLock((Handle)theAnimTxtr);
 
    /* save current port */
    GetGWorld(&oldGW, &oldGD);
 
    QuickTime_Init();
    
    success = QuickTime_GetNewMooVTexture(&(**theAnimTxtr).fMovie);  // Will prompt for movie file.
    if (!success) goto bail;
 
    GetMovieBox((**theAnimTxtr).fMovie, &bounds);
    
    err = NewGWorld(&pGWorld, 32, &bounds, 0, 0, useTempMem);
    if (err != noErr) {
        QuickTime_Delete(&(**theAnimTxtr).fMovie);
        success = false;
        goto bail;
    }
 
    success = true;
 
    hPixMap = GetGWorldPixMap(pGWorld);
    LockPixels(hPixMap);
    pictMapAddr  = (unsigned long)GetPixBaseAddr (hPixMap);
    pictRowBytes = (unsigned long)(**hPixMap).rowBytes & 0x3fff;
 
    SetGWorld(pGWorld, nil);
 
    strgPMap = &(**theAnimTxtr).fStoragePixmap;
    strgPMap->image = Q3MemoryStorage_NewBuffer(    (void *) pictMapAddr,
                                                    pictRowBytes * bounds.bottom,
                                                    pictRowBytes * bounds.bottom);
    strgPMap->width     = bounds.right;
    strgPMap->height    = bounds.bottom;
    strgPMap->rowBytes  = pictRowBytes;
    strgPMap->pixelSize = 32;
    strgPMap->pixelType = kQ3PixelTypeRGB32;
    strgPMap->bitOrder  = kQ3EndianBig;
    strgPMap->byteOrder = kQ3EndianBig;
 
    QuickTime_LoopMovie((**theAnimTxtr).fMovie, pGWorld);
 
    (**theAnimTxtr).fpGWorld = pGWorld;
 
bail:
    SetGWorld(oldGW, oldGD);
 
    HUnlock((Handle)theAnimTxtr);
 
    if (success)
        return theAnimTxtr;
    else
        return NULL;
}
 
/*===========================================================================*\
 *
 *  Routine:    AddTextureToGroup()
 *
 *  Comments:   Create a new textureShader based on the pixmap storage data.
 *              Add it to the group.
 *              
 *
\*===========================================================================*/
 
TQ3Status AddTextureToGroup(
            TQ3GroupObject      pGroup,
            TQ3StoragePixmap    *pStoragePixmap)
{
    TQ3TextureObject    textureObject;
    
    textureObject = Q3PixmapTexture_New(pStoragePixmap);
    if (textureObject != NULL)
    {
        /* New Texture Shader */
        TQ3ShaderObject textureShader;
        
        textureShader = Q3TextureShader_New(textureObject);
        Q3Object_Dispose(textureObject);
        
        if (textureShader != NULL)
        {
            TQ3GroupPosition    position;
            
            Q3Group_GetFirstPosition(pGroup, &position);
            Q3Group_AddObjectBefore(pGroup, position, textureShader);
            Q3Object_Dispose(textureShader);
            return kQ3Success;
        }
        else {
            /*ERROR_DEBUG_STR("AddTextureToGroup: Q3TextureShader_New failed.");*/
        }
    }
    else {
        /*ERROR_DEBUG_STR("AddTextureToGroup: Q3PixmapTexture_New failed.");*/
    }
 
    return kQ3Failure;
}
 
 
/*===========================================================================*\
 *
 *  Routine:    Texture_AddToGroup()
 *
 *  Comments:   Add fStoragePixmap to the group.
 *                  
 *
\*===========================================================================*/
 
TQ3Status Texture_AddToGroup(
            TAnimatedTextureHdl pAnimTxtr,
            TQ3GroupObject      pGroup)
{
    TQ3Status   status;
 
    status = kQ3Failure;
 
    if (pAnimTxtr   == NULL ||
        pGroup      == NULL)
    {
        /*ERROR_DEBUG_STR("AddMovieTextureToGroup: invalid parameters.");*/
        return status;
    }
 
    status = AddTextureToGroup(pGroup, &(**pAnimTxtr).fStoragePixmap);
 
    return status;
}
 
/*===========================================================================*\
 *
 *  Routine:    Texture_Delete()
 *
 *  Comments:   Dellocate the TAnimatedTexture.
 *                  Stop and delete fMovie, 
 *                  free fGWorld's memory,
 *                  and free memory used by fStorageMap.
 *
\*===========================================================================*/
 
Boolean Texture_Delete(
            TAnimatedTextureHdl pAnimTxtr)
{
    if ((**pAnimTxtr).fpGWorld == NULL)
        return false;
 
    HLock((Handle)pAnimTxtr);
 
    QuickTime_Delete(&(**pAnimTxtr).fMovie);
 
    DisposeGWorld((**pAnimTxtr).fpGWorld);
    (**pAnimTxtr).fpGWorld = NULL;
 
    if ((**pAnimTxtr).fStoragePixmap.image != NULL)
    {
        Q3Object_Dispose((**pAnimTxtr).fStoragePixmap.image);
        (**pAnimTxtr).fStoragePixmap.image = NULL;
    }
 
    HUnlock((Handle)pAnimTxtr);
    return true;
}
 
/*===========================================================================*\
 *
 *  Routine:    Texture_NextFrame()
 *
 *  Comments:   Advance the texture's movie to next frame
 *              and notify QD3D that the texture's image has changed.
 *                  
 *
\*===========================================================================*/
 
Boolean Texture_NextFrame(
        TAnimatedTextureHdl pAnimTxtr)
{
    
    TQ3StoragePixmap    *pStrgPMap;
    PixMapPtr           pPixMap;
    long                size;
    TQ3Status           status;
 
    /* If fGWorld is non-NULL then the fMovie is non-NULL
     * and the movie or video needs updating
     */
    if ((**pAnimTxtr).fpGWorld == NULL)
        return false;
 
    HLock((Handle)pAnimTxtr);
 
    if ((**pAnimTxtr).fMovie)
    {
        /* Draw next movie frame */
        MoviesTask((**pAnimTxtr).fMovie, 0);
    }
 
    pStrgPMap = &(**pAnimTxtr).fStoragePixmap;
 
    /* Tell QD3D the buffer changed */
    pPixMap = *((**pAnimTxtr).fpGWorld)->portPixMap;
    size    = pStrgPMap->height * pStrgPMap->rowBytes;
 
    status = Q3MemoryStorage_SetBuffer(
        pStrgPMap->image,
        (void *) pPixMap->baseAddr,
        size,
        size);
 
    HUnlock((Handle)pAnimTxtr);
    
    if (status == kQ3Success)
        return true;
    else
        return false;
}