GTShell.c

// Metafile read - shows how to read metafile data.
//
// Nick Thompson - January 6th 1994
//
// © 1995, Apple Computer Inc., All Rights Reserved
 
// system headers
#include <Devices.h>
#include <Dialogs.h>
#include <DiskInit.h>
#include <Fonts.h>
#include <Menus.h>
#include <PictUtils.h>
#include <QDOffScreen.h>
#include <QuickDraw.h>
#include <SegLoad.h>
#include <StandardFile.h>
#include <TextEdit.h>
#include <ToolUtils.h>
 
// for QuickDraw 3D
#include "QD3D.h"
#include "QD3DMath.h"
#include "QD3DDrawContext.h"
#include "QD3DShader.h"
#include "QD3DTransform.h"
#include "QD3DGroup.h"
#include "QD3DCamera.h"
 
#include "GTFile.h"
#include "GTShell.h"
#include "GTSupport.h"
 
#include "Geometries.h"
#include "MyErrorHandler.h"
#include "Error_Lib.h"
 
//-------------------------------------------------------------------------------------------
// function prototypes
 
static void         InitToolbox( void ) ;
static void         MainEventLoop( void ) ;
static void         HandleKeyPress(EventRecord *event) ;
static void         HandleOSEvent(EventRecord *event) ;
static TQ3Status    DocumentDraw3DData( DocumentHdl theDocument ) ;
static Boolean      IsAppWindow(WindowPtr window);
 
//-------------------------------------------------------------------------------------------
//
 
Boolean         gQuitFlag       = false ;
 
//-------------------------------------------------------------------------------------------
// main()
// entry point for the application, initialize the toolbox, initialize QuickDraw 3D
// and enter the main event loop.  On exit from the main event loop, we want to call
// the QuickDraw 3D exit function to clean up QuickDraw 3d.
 
void main(void)
{
    TQ3Status   myStatus;
    Rect        rBounds = { 50, 50, 350, 350 } ;
    Str255      title = "\pSpinning Box" ;
 
    InitToolbox() ;
        
    //  Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
    myStatus = Q3Initialize();
    if ( myStatus == kQ3Failure ) {
        DebugStr("\pErInitialize returned failure.");   
        ExitToShell() ;
    }
                    
    // install the error handler - this gets called whenever
    // an error occurs, which means we don't have to check so 
    // much
    InstallDefaultErrorHandler();
    InstallDefaultWarningHandler();
    InstallDefaultNoticeHandler();
 
    // set up our globals
    gQuitFlag = false ;
    
    // loop till we doop
    MainEventLoop();
    
    //  Close our connection to the QuickDraw 3D library
    myStatus = Q3Exit();
    if ( myStatus == kQ3Failure )
        DebugStr("\pErExit returned failure.");
}   
 
 
//-----------------------------------------------------------------------------
// assumes the port is set up before being called
 
TQ3Status DocumentDraw3DData( DocumentHdl theDocument )
{
//{
//  TQ3CameraData       theCameraData ;
//  TQ3CameraObject     theCameraObject;
//  
//  Q3View_GetCamera(theDocument->fView, &theCameraObject);
//  Q3Camera_GetData(theCameraObject, &theCameraData);
//Debugger() ;
//
//}
    TQ3Status theStatus ;
        
    if((**theDocument).fModel != nil ) {
        HLock((Handle)theDocument );
        theStatus = Q3View_StartRendering((**theDocument).fView) ;
        do {
            theStatus = SubmitScene( theDocument ) ;
        } while (Q3View_EndRendering((**theDocument).fView) == kQ3ViewStatusRetraverse );
    
        HUnlock((Handle)theDocument );
    }   
    return theStatus ;  
 
    
}
 
 
//----------------------------------------------------------------------------------
 
//-------------------------------------------------------------------------------------------
//
 
short HiWrd(long aLong)
{
    return  (((aLong) >> 16) & 0xFFFF) ;
}
 
//-------------------------------------------------------------------------------------------
//
 
short LoWrd(long aLong)
{
    return  ((aLong) & 0xFFFF) ;
 
}
//-------------------------------------------------------------------------------------------
//  IsAppWindow
//
//  Check to see if a window belongs to the application. If the window pointer
//  passed was NIL, then it could not be an application window. WindowKinds
//  that are negative belong to the system and windowKinds less than userKind
//  are reserved by Apple except for windowKinds equal to dialogKind, which
//  mean it is a dialog.
 
static Boolean IsAppWindow(WindowPtr window)
{
    short       windowKind;
 
    if ( window == nil )
        return false;
    else {
        windowKind = ((WindowPeek) window)->windowKind;
        return ((windowKind >= userKind) || (windowKind == dialogKind));
    }
}
 
 
//-------------------------------------------------------------------------------------------
//  IsDAWindow
//
//  Check to see if a window belongs to a desk accessory. It belongs to a DA
//  if the windowKind field of the window record is negative.
 
static Boolean IsDAWindow(WindowPtr window)
{
    if ( window == nil )
        return false;
    else
        return ( ((WindowPeek) window)->windowKind < 0 );
}
 
 
//-------------------------------------------------------------------------------------------
//  IsDialogWindow
//
//  Check to see if a window is a dialog window. We can determine this be
//  checking to see if the windowKind field is equal to dialogKind.
 
static Boolean IsDialogWindow(WindowPtr window)
{
    if ( window == nil )
        return false;
    else
        return ( ((WindowPeek) window)->windowKind == dialogKind );
}
 
 
//-------------------------------------------------------------------------------------------
//
static void AdjustMenus()
{
    WindowPtr   window;
    MenuHandle  menu;
 
    window = FrontWindow();
 
    menu = GetMHandle(mFile);
    
    if ( window != nil )
        EnableItem(menu, iClose);
    else
        DisableItem(menu, iClose);
 
    menu = GetMHandle(mEdit);
    if ( IsDAWindow(window) ) {
        EnableItem(menu, iUndo);
        EnableItem(menu, iCut);
        EnableItem(menu, iCopy);
        EnableItem(menu, iClear);
        EnableItem(menu, iPaste);
    } else {                        
        DisableItem(menu, iUndo);
        DisableItem(menu, iCut);
        DisableItem(menu, iCopy);
        DisableItem(menu, iClear);
        DisableItem(menu, iPaste);
    }
}
 
//-------------------------------------------------------------------------------------------
//
void InitToolbox()
{
    Handle      menuBar;
    EventRecord event;
    short       count;
 
    // initialize application globals
    gQuitFlag = false;
    
    MaxApplZone() ;
    MoreMasters() ; MoreMasters() ; MoreMasters() ; 
    
    // Init the managers
    InitGraf( &qd.thePort );
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(nil);
 
 
    FlushEvents( everyEvent, 0 ) ;
        
    //  This next bit of code waits until the Finder brings our application
    //  to the front. This gives us a better effect if we open a window at
    //  startup.
 
    for (count = 1; count <= 3; ++count)
        EventAvail(everyEvent, &event);
 
    menuBar = GetNewMBar( 128 );
    if ( menuBar == nil )
         ExitToShell() ;
         
    SetMenuBar( menuBar );
    DisposHandle( menuBar );
    AddResMenu( GetMHandle(mApple), 'DRVR' );   // Add DA names to Apple menu
    AdjustMenus();
    DrawMenuBar();
    InitCursor();                               // reset the cursor
}
 
//-------------------------------------------------------------------------------------------
//  HandleMenuCommand
//
//  This is called when an item is chosen from the menu bar (after calling
//  MenuSelect or MenuKey). It performs the right operation for each command.
//  It is good to have both the result of MenuSelect and MenuKey go to one
//  routine like this to keep everything organized.
 
static void HandleMenuCommand(long  menuResult)
{
    short       menuID;             // Resource ID# of the selected menu
    short       menuItem;           // Item number of the selected menu
    Str255      daName;
    DialogPtr   theDialog ; 
    short       itemHit ;
    WindowPtr   theWindow ;
 
    menuID = HiWrd(menuResult);
    menuItem = LoWrd(menuResult);
    switch ( menuID ) {
        case mApple:
            switch ( menuItem ) {
                ModalFilterUPP      theProc ;
 
                case iAbout:
                
                    theDialog = GetNewDialog ( 128, nil, (WindowPtr)-1 );
                    
                    // these two lil' snappers are system 7 only
                    // so if you use them, check before!!
                    GetStdFilterProc( &theProc ) ;
                    SetDialogDefaultItem(theDialog, ok) ;
                    
                    
                    do {
                        ModalDialog ( theProc, &itemHit );
                    } while( itemHit != ok ) ;
                    DisposDialog ( theDialog );
                    break;
 
                default:            // All non-About items in this menu are DAs
                    GetItem(GetMHandle(mApple), menuItem, daName);
                    (void) OpenDeskAcc(daName);
                    break;
            }
            break;
        case mFile:
            switch ( menuItem ) {
                case iNew:
                    HandleNewCommand() ;
                    break;
                case iOpen:
                    HandleOpenCommand() ;
                    break;
                case iClose:
                    HandleCloseWindow( FrontWindow() ) ;
                    break;
                case iQuit:
                    gQuitFlag = true;
                    break;
            }
            break;
        case mEdit:
            switch (menuItem) {
                // Call SystemEdit for DA editing & MultiFinder 
                // since we donÕt do any Editing yet
                case iUndo:
                case iCut:
                case iCopy:
                case iPaste:
                case iClear:
                    (void) SystemEdit(menuItem-1);
                    break;
            }
            break;
            
        case mGeometry:
            theWindow = FrontWindow() ;
            if (theWindow == NULL){
                HandleNewCommand();
            }
 
            theWindow = FrontWindow() ;
            if( theWindow ) {
                DocumentHdl theDocument = (DocumentHdl) GetWRefCon( theWindow ) ;
                if( theDocument != nil ) {
                    TQ3Point3D      myOrigin = { 0, 0, 0 } ;
                
                    HLock( (Handle)theDocument ) ;
                    
                    if((**theDocument).fModel != nil) {
                        Q3Object_Dispose((**theDocument).fModel) ;              
                        (**theDocument).fModel = nil ;
                    }
                    
                    (**theDocument).fModel = BuildGeometry(menuItem) ;
                    
                    (**theDocument).fGroupScale = 1;                
                    (**theDocument).fGroupCenter = myOrigin ;           
                    AdjustCamera(   theDocument,
                                    (theWindow->portRect.right - theWindow->portRect.left),
                                    (theWindow->portRect.bottom - theWindow->portRect.top) ) ;
                                    
                    HUnlock((Handle)theDocument);
                }
                SetPort( (GrafPtr)theWindow ) ;
                InvalRect( & theWindow->portRect ) ;
            }
            break ;
    }
    HiliteMenu(0);      // Unhighlight what MenuSelect or MenuKey hilited
}
 
//-------------------------------------------------------------------------------------------
//
void MainEventLoop()
{
    EventRecord     event;
    WindowPtr       window;
    short           thePart;
    Rect            screenRect, updateRect;
    Point           aPoint = {100, 100};
    CGrafPtr        savedPort ;
    
    DocumentHdl     theDocument ;
    
 
    while( !gQuitFlag )
    {
        if (WaitNextEvent( everyEvent, &event, 0, nil ))
        {
 
            switch (event.what) {
                case mouseDown:
                
                    thePart = FindWindow( event.where, &window );
                    
                    switch( thePart ) {
                        case inMenuBar: 
                            AdjustMenus();
                            HandleMenuCommand(MenuSelect(event.where));
                            break;
                        
                        case inDrag:
                    
                            screenRect = (**GetGrayRgn()).rgnBBox;
                            DragWindow( window, event.where, &screenRect );
                            break ;
                    
                        case inContent:
                    
                            if (window != FrontWindow())
                                SelectWindow( window );
                            break ;
                    
                        case inGoAway:
                            if (TrackGoAway( window, event.where )) {
                                HandleCloseWindow( window ) ;
                            }
                            break ;
                            
                        default:
                            break ;
                    }
                    break ;
                            
                        
                case updateEvt:
                
                    window = (WindowPtr)event.message;
                    theDocument = (DocumentHdl) GetWRefCon( window ) ;
                    
                    if( theDocument != nil ) {
                        updateRect = (**(window->visRgn)).rgnBBox;
                        
                        GetPort( (GrafPtr *)&savedPort) ;
                        SetPort( window ) ;
                        BeginUpdate( window );
                        DocumentDraw3DData( theDocument ) ;
                        EndUpdate( window );
                        SetPort( (GrafPtr)savedPort ) ;
                    }
 
                    break ;
                    
                case keyDown:
                case autoKey:
                    HandleKeyPress(&event);
                    break;
                    
                case diskEvt:
                    if ( HiWrd(event.message) != noErr ) 
                        (void) DIBadMount(aPoint, event.message);
                    break;
                    
                case osEvt:
                case activateEvt:
                    break;
 
 
            }
        }
        else {
            
            window = FrontWindow() ;
            if( window ) {
                if(IsAppWindow(window)){
                    theDocument = (DocumentHdl) GetWRefCon( window ) ;
                    if( theDocument != nil ) {
 
                        // we received a null event, rotate the object
                        TQ3Matrix4x4    tmp;
                        Rect        theRect = (window)->portRect ;
                        
                        SetPort(window) ;
                        Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
                        HLock( (Handle)theDocument ) ;
                        Q3Matrix4x4_Multiply(&(**theDocument).fRotation, &tmp, &(**theDocument).fRotation);
                        HUnlock( (Handle)theDocument ) ;
            
                        InvalRect( &theRect ) ;
                    }
                }
            }
        }
    }
 
    /* Close all windows */
    window = FrontWindow() ;
    while (window != nil) {
        HandleCloseWindow( window ) ;
        window = FrontWindow() ;
    }
}
 
 
//-------------------------------------------------------------------------------------------
//
void HandleKeyPress(EventRecord *event)
{
    char    key;
 
    key = event->message & charCodeMask;
    if ( event->modifiers & cmdKey ) {      /* Command key down? */
        AdjustMenus();                      /* Enable/disable/check menu items properly */
        HandleMenuCommand(MenuKey(key));
    } else {
        /* DoKeyPress(event) */;
    }
}
 
//-------------------------------------------------------------------------------------------
//