home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Frameworks / Hsoi's App Shell 1.0a4 / Hsoi's App Shell Source / HASCoolAboutBox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-28  |  23.9 KB  |  936 lines  |  [TEXT/CWIE]

  1. /*    
  2.     HASCoolAboutBox.c from Hsoi's App Shell ©1995-1997 John C. Daub.  All rights reserved.
  3.     
  4.     This is a "neat" About box.  Much better than the plain old about boxes.
  5.     Plus, it's sorta my attempt at an "Easter Egg" for the app shell.
  6.     
  7.     It has animation and uses GWorlds for that animation.  I gleaned how to do
  8.     this sorta thing from Metrowerk's own About box (they included the code on
  9.     how to do this sorta thing on their CD in the "Examples" folder).
  10. */
  11.  
  12. #pragma mark ••• #includes •••
  13.  
  14. #ifndef _WASTE_
  15. #include "WASTE.h"
  16. #endif
  17. #include "HASGlobals.h"
  18. #ifndef __HSOIS_APP_SHELL__
  19. #include "HASMain.h"
  20. #endif
  21. #include "HASCoolAboutBox.h"
  22. #include "HASUtilities.h"
  23. #include "HASMiscEvents.h"
  24.  
  25. #include "WASTE_Objects.h"
  26.  
  27. #ifndef __QDOFFSCREEN__
  28. #include <QDOffscreen.h>
  29. #endif
  30.  
  31. #pragma mark -
  32. #pragma mark ••• Public Call •••
  33.  
  34.  
  35. // the big meat call that starts it all
  36.  
  37. void    HsoiDoCoolAboutBox( void )
  38. {
  39.     GWorldPtr        saveWorld;
  40.     GDHandle        saveDevice;
  41.  
  42.     // if we have a WASTE sound playing, stop it before proceeding.
  43.     
  44.     if ( SoundIsPlaying() )
  45.         StopCurrentSound();
  46.  
  47.     // we should check for system 7, having color quickdraw, and even for the monitor
  48.     // to 256 color pixels (or greater, if not already there), but since we know this
  49.     // is working within the realmz of a System 7 app, we don't need to.  However,
  50.     // it'd probably be a good thing to throw the checks in here anyways, y'know?
  51.  
  52.     // save the current GWorlds
  53.     
  54.     GetGWorld( &saveWorld, &saveDevice );
  55.     
  56.     // see if we have some free memory running about
  57.     
  58.     if ( FreeMem() < 350000 )
  59.     {
  60.         SysBeep( 5 );
  61.         return;
  62.     }
  63.     
  64.     // deactivate the front window
  65.     
  66.     HsoiDoActivate( false, FrontWindow() );
  67.     
  68.     // set things up
  69.     
  70.     HsoiSetUpCoolAboutBox();
  71.     
  72.     // do the stuff
  73.     
  74.     HsoiDoCoolStuff();
  75.     
  76.     // clean up
  77.     
  78.     HsoiCleanUpCoolAboutBox();
  79.  
  80.     // reactivate the "front" window
  81.         
  82.     HsoiDoActivate( true, FrontWindow() );
  83.     
  84.     // and restore our GWorlds
  85.     
  86.     SetGWorld( saveWorld, saveDevice );
  87.     
  88.     return;
  89. }
  90.  
  91. #pragma mark -
  92. #pragma mark ••• Setup Routines •••
  93.  
  94.  
  95. // this is the setup routine that gets everything ready to go
  96.  
  97. void    HsoiSetUpCoolAboutBox( void )
  98. {
  99.     Rect            backgroundRect;
  100.     PixMapHandle    hPixMap;
  101.     OSErr            err;
  102.  
  103.     // get an area equal to our background
  104.         
  105.     HsoiGetItemRect( iCoolAboutBkgrnd, &backgroundRect );
  106.     
  107.     // try to create a gworld that size to draw the background into
  108.     
  109.     err = NewGWorld( &gDrawWorldPtr, PIXEL_DEPTH, &backgroundRect, nil, nil, 0 );
  110.     
  111.     // if we've run out of memory, try tapping temporary memory
  112.     
  113.     if ( err == memFullErr ) // -108
  114.         err = NewGWorld( &gDrawWorldPtr, PIXEL_DEPTH, &backgroundRect, nil, nil, 0 + useTempMem );
  115.     
  116.     // get a handle to the pixel map for the offscreen world
  117.     
  118.     hPixMap = GetGWorldPixMap( gDrawWorldPtr );
  119.     
  120.     // lock the handle hi in the heap
  121.     
  122.     HLockHi( (Handle)hPixMap );
  123.     
  124.     // lock the offscren buffer
  125.     
  126.     LockPixels( hPixMap );
  127.     
  128.     // readjust a few things
  129.     
  130.     gDrawPixMapPtr = *hPixMap;
  131.     
  132.     
  133.     // make gworld for the background
  134.     
  135.     // draw the background pict into the background gworld
  136.     
  137.     HsoiDrawPictIntoNewGWorld( rCoolAboutBkgrndPICT, PIXEL_DEPTH, &gBackWorldPtr );
  138.     
  139.     // get a handle to the pixmap
  140.     
  141.     hPixMap = GetGWorldPixMap( gBackWorldPtr );
  142.  
  143.     // lock the handle hi
  144.     
  145.     HLockHi( (Handle)hPixMap );
  146.     
  147.     // lock the offscreen buffer
  148.     
  149.     LockPixels( hPixMap );
  150.     
  151.     // and again, readjust the variables
  152.     
  153.     gBackPixMapPtr = *hPixMap;
  154.     
  155.     // get us a window...
  156.     
  157.     aboutBoxWindow = (CWindowPtr)GetNewCWindow( rCoolAboutWIND, nil, MOVE_TO_FRONT );
  158.     
  159.     // show it
  160.     
  161.     ShowWindow( (WindowRef)aboutBoxWindow );
  162.     
  163.     // lock hi the window's port pixel map
  164.     
  165.     HLockHi( (Handle)aboutBoxWindow->portPixMap );
  166.     windowPixMapPtr = *aboutBoxWindow->portPixMap;
  167.     
  168.     // draw the background in the window
  169.     
  170.     SetGWorld( aboutBoxWindow, GetMainDevice() );
  171.     CopyBits( (BitMapPtr)gBackPixMapPtr, (BitMapPtr)windowPixMapPtr, &backgroundRect,
  172.                 &backgroundRect, srcCopy, nil );
  173.     
  174.     
  175.     return;
  176. }
  177.  
  178.  
  179. // set up our logo picture
  180.  
  181. void    HsoiSetUpLogo( LogoRec *inLogoBoxRec )
  182. {
  183.     // draw the logo pict into a new gworld
  184.     
  185.     HsoiDrawPictIntoNewGWorld( rLogoPICT, PIXEL_DEPTH, &inLogoBoxRec->theGWorldPtr );
  186.     
  187.     // and all this places our pict in a nice starting location
  188.     
  189.     HsoiGetItemRect( iCoolAboutLogo, &inLogoBoxRec->currPos );
  190.     inLogoBoxRec->bottomLoc = inLogoBoxRec->currPos.bottom;
  191.     OffsetRect( &inLogoBoxRec->currPos, 0, -inLogoBoxRec->currPos.bottom );
  192.     inLogoBoxRec->imagePos.left = inLogoBoxRec->imagePos.top = 0;
  193.     inLogoBoxRec->imagePos.right = inLogoBoxRec->currPos.right - inLogoBoxRec->currPos.left;
  194.     inLogoBoxRec->imagePos.bottom = inLogoBoxRec->currPos.bottom - inLogoBoxRec->currPos.top;
  195.     
  196.     return;
  197. }
  198.  
  199. // set up for version pict
  200.  
  201. void    HsoiSetUpVersion( VersionRec *inVersionBoxRec )
  202. {
  203.     Rect        bkgndRect;
  204.     
  205.     // draw the version pict into a new gworld
  206.     
  207.     HsoiDrawPictIntoNewGWorld( rVersionPICT, PIXEL_DEPTH, &inVersionBoxRec->theGWorldPtr );
  208.     
  209.     // and place the pict in a nice starting place offscreen
  210.     
  211.     HsoiGetItemRect( iCoolAboutVersion, &inVersionBoxRec->currPos );
  212.     HsoiGetItemRect( iCoolAboutBkgrnd, &bkgndRect );
  213.     inVersionBoxRec->bottomLoc = inVersionBoxRec->currPos.bottom;
  214.     OffsetRect( &inVersionBoxRec->currPos, 0, ( bkgndRect.bottom - inVersionBoxRec->currPos.top) );
  215.     inVersionBoxRec->imagePos.left = inVersionBoxRec->imagePos.top = 0;
  216.     inVersionBoxRec->imagePos.right = inVersionBoxRec->currPos.right - inVersionBoxRec->currPos.left;
  217.     inVersionBoxRec->imagePos.bottom = inVersionBoxRec->currPos.bottom - inVersionBoxRec->currPos.top;
  218.         
  219.     return;
  220. }
  221.  
  222. // set up the credits
  223.  
  224. void    HsoiSetUpCredits(CreditsRec *inCreditsRec)
  225. {
  226.     PicHandle         pictureH;
  227.     Rect             picFrame;
  228.     PixMapHandle     thePixMapH;
  229.     Rect            creditsBox;
  230.     OSErr            err;
  231.     
  232.     //    The only animation is the credits
  233.     //    Therefore, we can reduce the size of the offscreen worlds for the background
  234.     //    and scratch drawing to just cover the area where the credits are drawn.
  235.  
  236.     DisposeGWorld(gBackWorldPtr);
  237.     DisposeGWorld(gDrawWorldPtr);
  238.  
  239.     HsoiGetItemRect(iCoolAboutText, &inCreditsRec->viewRect);
  240.  
  241.     //    Make GWorld for offscreen drawing.
  242.  
  243.     err = NewGWorld(&gDrawWorldPtr, PIXEL_DEPTH, &inCreditsRec->viewRect, nil, nil, 0);
  244.     if ( err == memFullErr )
  245.         err = NewGWorld( &gDrawWorldPtr, PIXEL_DEPTH, &inCreditsRec->viewRect, nil, nil, 0 + useTempMem );
  246.     thePixMapH = GetGWorldPixMap(gDrawWorldPtr);
  247.     HLockHi((Handle)thePixMapH);
  248.     LockPixels(thePixMapH);
  249.     gDrawPixMapPtr = *thePixMapH;
  250.  
  251.     //    Make GWorld for background.
  252.  
  253.     err = NewGWorld(&gBackWorldPtr, PIXEL_DEPTH, &inCreditsRec->viewRect, nil,
  254.               GetGWorldDevice(gDrawWorldPtr), noNewDevice);
  255.     if ( err == memFullErr )
  256.         NewGWorld( &gBackWorldPtr, PIXEL_DEPTH, &inCreditsRec->viewRect, nil,
  257.                 GetGWorldDevice( gDrawWorldPtr), noNewDevice + useTempMem );
  258.     thePixMapH = GetGWorldPixMap(gBackWorldPtr);
  259.     HLockHi((Handle)thePixMapH);
  260.     LockPixels(thePixMapH);
  261.     gBackPixMapPtr = *thePixMapH;
  262.  
  263.     // draw the background pict into it's own little gworld
  264.     
  265.     SetGWorld(gBackWorldPtr, nil);
  266.     pictureH = GetPicture(rCoolAboutBkgrndPICT);
  267.     picFrame = (**pictureH).picFrame;
  268.     DrawPicture(pictureH, &picFrame);
  269.     HsoiForgetResource( (Handle *)&pictureH );
  270.  
  271.     //    Make GWorld for credits.
  272.     
  273.     creditsBox = inCreditsRec->viewRect;
  274.     HsoiDrawTextIntoNewGWorld(rCoolAboutCreditsText, &creditsBox,
  275.             PIXEL_DEPTH, &inCreditsRec->theGWorldPtr);
  276.             
  277.     inCreditsRec->pictRect.left = 0;
  278.     inCreditsRec->pictRect.top = 0;
  279.     inCreditsRec->pictRect.right = inCreditsRec->viewRect.right -
  280.         inCreditsRec->viewRect.left;
  281.     inCreditsRec->pictRect.bottom = inCreditsRec->viewRect.bottom -
  282.         inCreditsRec->viewRect.top;
  283.         
  284.     inCreditsRec->pictHeight = creditsBox.bottom;
  285.     
  286.     return;
  287. }
  288.  
  289. // just what you think...dispose of stuff
  290.  
  291. void    HsoiCleanUpCoolAboutBox( void )
  292. {
  293.     DisposeGWorld( gDrawWorldPtr );
  294.     DisposeGWorld( gBackWorldPtr );
  295.     DisposeWindow( (WindowRef)aboutBoxWindow );
  296.     return;
  297. }
  298.  
  299.  
  300. #pragma mark -
  301. #pragma mark ••• Animation •••
  302.  
  303. // this does all the cool animation and action in the box
  304.  
  305. void    HsoiDoCoolStuff( void )
  306. {
  307.     /*    start on the cool stuff...
  308.     
  309.         Have the logo bounce in...the version bounce in...the credits fade in and then
  310.         scroll through.  after scrolling through, it'll pause a bit at the end,
  311.         then automatically dismiss.  It used to wrap the credits around and scroll
  312.         continuously, but I removed that...it seems to hate life if tempMem is
  313.         used for the GWorlds
  314.     */
  315.     
  316.     CreditsRec            theCreditsRec;
  317.     LogoRec                theLogoRec;
  318.     VersionRec            theVersionRec;
  319.     Rect                currPos, imagePos;
  320.     
  321.     AnimateState        animLogoDown = animate_Active;
  322.     AnimateState        animLogoUp = animate_Waiting;
  323.     AnimateState        animVersionDown = animate_Waiting;
  324.     AnimateState        animVersionUp = animate_Waiting;
  325.     AnimateState        animVersion = animate_Waiting;
  326.     AnimateState        animCreditsFade = animate_Waiting;
  327.     AnimateState        animCreditsScroll = animate_Waiting;
  328.     
  329.     Boolean                logoHalfDrawn = false;
  330.     Boolean                logoWholeDrawm = false;
  331.  
  332.     RGBColor            fadeColor;
  333.     short                grayIndex = 0;
  334.     unsigned short        grayLevels[FADE_LEVELS] = {
  335.         4369, 8738, 17476, 21845, 30583, 34952, 43690, 48059, 52428, 56979,
  336.         61166, 65535
  337.     };
  338.  
  339.     // initialize things
  340.         
  341.     theLogoRec.theGWorldPtr = nil;
  342.     theVersionRec.theGWorldPtr = nil;
  343.     theCreditsRec.theGWorldPtr = nil;
  344.     
  345.     // set up the logo
  346.     
  347.     HsoiSetUpLogo( &theLogoRec );
  348.     
  349.     // set up the version picture
  350.     
  351.     HsoiSetUpVersion( &theVersionRec );
  352.     
  353.     // and begin the big mama loop to make it all go
  354.     
  355.     // but before we go, let's flush the event queue a bit
  356.     
  357.     FlushEvents(mDownMask | mUpMask | keyDownMask | keyUpMask | autoKeyMask, 0);
  358.     
  359.     
  360.     while ( !Button() ) // a mouse click will end it all
  361.     {
  362.         long        ticks;
  363.         long        endTicks;
  364.         long        startTicks = TickCount();
  365.     
  366.         // the following things are kinda confusing...what we're doing is constantly
  367.         // monitoring the state of the animating things...based upon the state of
  368.         // one thing, we'll determine the state of the next thing and then go from
  369.         // there...again, it's kinda confusing, so read it over a bunch of times.
  370.         // eventually, it'll sink in and make sense (i hope!)
  371.     
  372.         // if the logo is the current active object and it's gone down as far as
  373.         // we want it, set a few things to let us know it's time to move it up
  374.         
  375.         if ( (animLogoDown == animate_Active) &&
  376.              (theLogoRec.currPos.bottom >= theLogoRec.bottomLoc + BOUNCE ))
  377.         {
  378.             animLogoDown = animate_Done;
  379.             animLogoUp = animate_Active;
  380.         }
  381.         
  382.         // if the logo is the current active object and it's now moved all the way
  383.         // up and is in it's final resting place, we don't need to animate it anymore,
  384.         // and we'll now start the version animating
  385.         
  386.         if ( (animLogoUp == animate_Active) && 
  387.              (theLogoRec.currPos.bottom <= theLogoRec.bottomLoc) )
  388.         {
  389.             animLogoUp = animate_Done;
  390.             animVersionUp = animate_Active;
  391.         }
  392.         
  393.         // if the version is the current active object and it's moved up as far as
  394.         // it should, time to bounce it back down into place
  395.         
  396.         if ( (animVersionUp == animate_Active ) && 
  397.             (theVersionRec.currPos.bottom <= theVersionRec.bottomLoc ) )
  398.              
  399.         {
  400.             animVersionUp = animate_Done;
  401.             animVersionDown = animate_Active;
  402.         }
  403.         
  404.         // HERE'S A BIG ONE!
  405.         
  406.         // the logo and version picts are all in place...it's now time to
  407.         // start on the scrolling credits...first we'll have to fade them in,
  408.         // so we'll have to get them all set up!
  409.         
  410.         if ( (animVersionDown == animate_Active) && 
  411.             (theVersionRec.currPos.bottom >= theVersionRec.bottomLoc + BOUNCE ) )
  412.         {
  413.             animVersionDown = animate_Done;
  414.             animCreditsFade = animate_Active;
  415.             HsoiSetUpCredits( &theCreditsRec );
  416.         }
  417.         
  418.         //  if the credits have totally faded in, wait a sec and a half,
  419.         // then begin to scroll 'em.
  420.         
  421.         if ( (animCreditsFade == animate_Active) &&
  422.              (grayIndex >= FADE_LEVELS))
  423.         {
  424.             animCreditsFade = animate_Done;
  425.             Delay( 90, &ticks );
  426.             animCreditsScroll = animate_Active;
  427.         }
  428.         
  429.         // if the text has scrolled all the way through, time to bail
  430.         // out and go bye bye (originally, this is where things would be reset
  431.         // to allow the scrolling text to loop back to the beginning)
  432.         
  433.         if ( (animCreditsScroll == animate_Active) &&
  434.              (theCreditsRec.pictRect.top > theCreditsRec.pictHeight))
  435.         {
  436.             theCreditsRec.pictRect.top = 1;
  437.             theCreditsRec.pictRect.top = theCreditsRec.viewRect.bottom - theCreditsRec.viewRect.top + 1;
  438.             goto byebye;
  439.         }
  440.         
  441.         
  442.         // alright...all the above stuff was just the setting up of the animate
  443.         // states....now, based upon those, we now will commence to do things..
  444.         
  445.         
  446.         // we want to move the logo down, so let's adjust coordinates as such
  447.         
  448.         if ( animLogoDown == animate_Active )
  449.         {
  450.             currPos = theLogoRec.currPos;
  451.             theLogoRec.currPos.top++;
  452.             theLogoRec.currPos.bottom++;
  453.             imagePos = theLogoRec.imagePos;
  454.             HsoiMoveOffWorld( theLogoRec.theGWorldPtr, &currPos, &theLogoRec.currPos, &imagePos );
  455.         }
  456.         
  457.         // and now move the logo up, so adjust coordinates as such
  458.         
  459.         if ( animLogoUp == animate_Active )
  460.         {
  461.             currPos = theLogoRec.currPos;
  462.             theLogoRec.currPos.top--;
  463.             theLogoRec.currPos.bottom--;
  464.             imagePos = theLogoRec.imagePos;
  465.             HsoiMoveOffWorld( theLogoRec.theGWorldPtr, &currPos, &theLogoRec.currPos, &imagePos );
  466.         }
  467.         
  468.         // move the version up, so adjust coordinates to suit
  469.         
  470.         if ( animVersionUp == animate_Active )
  471.         {
  472.             currPos = theVersionRec.currPos;
  473.             theVersionRec.currPos.top--;
  474.             theVersionRec.currPos.bottom--;
  475.             imagePos = theVersionRec.imagePos;
  476.             HsoiMoveOffWorld( theVersionRec.theGWorldPtr, &currPos, &theVersionRec.currPos, &imagePos );
  477.         }
  478.         
  479.         // move the version down, again, adjust coordinates
  480.         
  481.         if ( animVersionDown == animate_Active )
  482.         {
  483.             currPos = theVersionRec.currPos;
  484.             theVersionRec.currPos.top++;
  485.             theVersionRec.currPos.bottom++;
  486.             imagePos = theVersionRec.imagePos;
  487.             HsoiMoveOffWorld( theVersionRec.theGWorldPtr, &currPos, &theVersionRec.currPos, &imagePos );
  488.         }
  489.         
  490.         // we're going to fade in the credits from black
  491.  
  492.         if ( animCreditsFade == animate_Active )
  493.         {
  494.             PixMapHandle    thePixMapH;
  495.             
  496.             // delay for a 1/20th of a second
  497.             
  498.             Delay( 3, &ticks );
  499.             
  500.             // set our gworld up
  501.             
  502.             SetGWorld( gDrawWorldPtr, nil );
  503.             
  504.             // get the credit's pixel map
  505.             
  506.             thePixMapH = GetGWorldPixMap( theCreditsRec.theGWorldPtr );
  507.             
  508.             // lock 'em for drawing
  509.             
  510.             LockPixels(thePixMapH);
  511.             
  512.             // and copy
  513.             
  514.             CopyBits( (BitMapPtr)(*thePixMapH), (BitMapPtr)gDrawPixMapPtr,
  515.                         &theCreditsRec.pictRect, &theCreditsRec.viewRect, srcCopy, nil );
  516.             
  517.             // unlock the pixels
  518.             
  519.             UnlockPixels( thePixMapH );
  520.             
  521.             // change the color (incrimentally), from black to white
  522.             
  523.             fadeColor.red = fadeColor.blue = fadeColor.green = grayLevels[grayIndex++];
  524.             
  525.             // set this new color
  526.             
  527.             RGBForeColor( &fadeColor );
  528.             
  529.             // set our pen mode
  530.             
  531.             PenMode( adMin );
  532.             
  533.             // paint the viewRect
  534.             
  535.             PaintRect( &theCreditsRec.viewRect );
  536.             
  537.             // set the pen mode again
  538.             
  539.             PenMode( patCopy );
  540.             
  541.             // and make things black
  542.             
  543.             ForeColor( blackColor );
  544.             
  545.             // copy from the background
  546.             
  547.             CopyBits( (BitMapPtr)gBackPixMapPtr, (BitMapPtr)gDrawPixMapPtr,
  548.                         &theCreditsRec.viewRect, &theCreditsRec.viewRect, adMax, nil );
  549.             
  550.             // set to our onscreen about box
  551.             
  552.             SetGWorld( aboutBoxWindow, GetMainDevice() );
  553.             
  554.             // and finally, copy things onscreen
  555.             
  556.             CopyBits( (BitMapPtr)gDrawPixMapPtr, (BitMapPtr)windowPixMapPtr,
  557.                         &theCreditsRec.viewRect, &theCreditsRec.viewRect, srcCopy, nil );
  558.         }
  559.         
  560.         // if it's time to scroll the credits...
  561.         
  562.         if ( animCreditsScroll == animate_Active )
  563.         {
  564.             PixMapHandle        thePixMapH;
  565.             short                i, j;
  566.             short                creditsWidth = theCreditsRec.viewRect.right - theCreditsRec.viewRect.left - 1;
  567.             
  568.             // set the gworld to a "scrap" drawing gworld
  569.             
  570.             SetGWorld( gDrawWorldPtr, nil );
  571.             
  572.             // set up the rect's coordinates...bump up 1 pixel to make the scroll happen
  573.             
  574.             theCreditsRec.pictRect.top += 1;
  575.             theCreditsRec.pictRect.bottom += 1;
  576.             
  577.             // get the pix map
  578.             
  579.             thePixMapH = GetGWorldPixMap( theCreditsRec.theGWorldPtr );
  580.             LockPixels( thePixMapH );
  581.             
  582.             // if we haven't scrolled all the way through...
  583.             
  584.             if ( theCreditsRec.pictRect.bottom <= theCreditsRec.pictHeight)
  585.             {
  586.                 // copy into our scrap gworld for nice "editing"
  587.                 
  588.                 CopyBits( (BitMapPtr)(*thePixMapH), (BitMapPtr)gDrawPixMapPtr,
  589.                             &theCreditsRec.pictRect, &theCreditsRec.viewRect, srcCopy, nil );
  590.             }
  591.             
  592.             UnlockPixels( thePixMapH );
  593.             
  594.             // set our pen mode
  595.             
  596.             PenMode( adMin );
  597.             
  598.             // and we do a nice little touch here...at the top and bottom of the
  599.             // credits, instead of just going in and out of the screen, we have a nice
  600.             // little fade effect.
  601.             
  602.             // this loop makes the fade nice and gradual
  603.             
  604.             j = FADE_LEVELS - 1;
  605.             for ( i = 0; i < j; i++ )
  606.             {
  607.                 fadeColor.red = fadeColor.blue = fadeColor.green = grayLevels[i];
  608.                 RGBForeColor( &fadeColor );
  609.                 MoveTo( theCreditsRec.viewRect.left, theCreditsRec.viewRect.top + i);
  610.                 Line( creditsWidth, 0 );
  611.                 MoveTo( theCreditsRec.viewRect.left, theCreditsRec.viewRect.bottom - i - 1 );
  612.                 Line( creditsWidth, 0 );
  613.             }
  614.             
  615.             // set the fore color to black
  616.             
  617.             ForeColor( blackColor );
  618.             
  619.             // new pen mode
  620.             
  621.             PenMode( patCopy );
  622.             
  623.             // copy from the back to the scrap gworld
  624.             
  625.             CopyBits( (BitMapPtr)gBackPixMapPtr, (BitMapPtr)gDrawPixMapPtr,
  626.                         &theCreditsRec.viewRect, &theCreditsRec.viewRect, adMax, nil );
  627.             
  628.             // set the gworld to our abou box
  629.             
  630.             SetGWorld( aboutBoxWindow, GetMainDevice() );
  631.             
  632.             // and copy it all onscreen and give the illusion of scrolling :)
  633.             
  634.             CopyBits( (BitMapPtr)gDrawPixMapPtr, (BitMapPtr)windowPixMapPtr,
  635.                         &theCreditsRec.viewRect, &theCreditsRec.viewRect, srcCopy, nil );
  636.                     
  637.         }
  638.     
  639.         // a nice little buffer to pace the scrolling. if the user's computer is so
  640.         // way fast is blows through a cycle of the while-loop too fast, we don't
  641.         // want the credits to scroll by at a million miles an hour.  it's like
  642.         // a nice speed limit. :)
  643.         
  644.         endTicks = TickCount();
  645.         if ( endTicks == startTicks )
  646.             while ( endTicks == TickCount() )
  647.                 ;
  648.     } // end while (!Button())
  649.     
  650. byebye:
  651.  
  652.     // clean out the event queue
  653.  
  654.     FlushEvents(mDownMask | mUpMask | keyDownMask | keyUpMask | autoKeyMask, 0);
  655.     
  656.     // dispose of unneeded gworlds
  657.     
  658.     if ( theCreditsRec.theGWorldPtr != nil )
  659.         DisposeGWorld(theCreditsRec.theGWorldPtr );
  660.     if ( theLogoRec.theGWorldPtr != nil )
  661.         DisposeGWorld(theLogoRec.theGWorldPtr );
  662.     if ( theVersionRec.theGWorldPtr != nil )
  663.         DisposeGWorld( theVersionRec.theGWorldPtr );
  664.     
  665.     return;
  666. }
  667.  
  668. // this function is unused here...it's "left over" from the original Metrowerks
  669. // animated about box code
  670.  
  671. void HsoiMoveLogoBox(GWorldPtr theGWorldP, Rect *inCurrPos, short inVertOffset)
  672. {
  673. #pragma unused ( theGWorldP )
  674.  
  675.     Rect exposedRect, coveredRect, imageRect;
  676.     RGBColor boxColor =  {
  677.         65535, 52428, 0
  678.     };
  679.  
  680.     //    Draw to the Window.
  681.  
  682.     SetGWorld(aboutBoxWindow, GetMainDevice());
  683.  
  684.     //    Determine areas exposed and covered by bar as it moves.
  685.  
  686.     exposedRect = coveredRect = *inCurrPos;
  687.     if (inVertOffset > 0) {
  688.         exposedRect.bottom = exposedRect.top + inVertOffset;
  689.         coveredRect.top = coveredRect.bottom;
  690.         coveredRect.bottom += inVertOffset;
  691.     } else {
  692.         exposedRect.top = exposedRect.bottom + inVertOffset;
  693.         coveredRect.bottom = coveredRect.top;
  694.         coveredRect.top += inVertOffset;
  695.     }
  696.     imageRect.left = 0;
  697.     imageRect.right = coveredRect.right - coveredRect.left;
  698.     imageRect.top = 0;
  699.     imageRect.bottom = coveredRect.bottom - coveredRect.top;
  700.  
  701.     //    Restore background over exposed area.
  702.  
  703.     CopyBits((BitMapPtr)gBackPixMapPtr, (BitMapPtr)windowPixMapPtr, &exposedRect,
  704.              &exposedRect, srcCopy, nil);
  705.  
  706.     //    Draw image at covered area.
  707.  
  708.     RGBForeColor(&boxColor);
  709.     PaintRect(&coveredRect);
  710.     ForeColor(blackColor);
  711.     
  712.     return;
  713. }
  714.  
  715. void HsoiMoveOffWorld(GWorldPtr theGWorldP, Rect *inCurrPos, Rect *inNewPos, Rect *inOffPos)
  716. {
  717.     Rect drawRect;
  718.     PixMapHandle offPixMapH;
  719.  
  720.     //    Create image in draw world.
  721.  
  722.     SetGWorld(gDrawWorldPtr, nil);
  723.  
  724.     //    Restore background at current position.
  725.  
  726.     CopyBits((BitMapPtr)gBackPixMapPtr, (BitMapPtr)gDrawPixMapPtr, inCurrPos,
  727.              inCurrPos, srcCopy, nil);
  728.  
  729.     //    Draw image at new position.
  730.  
  731.     offPixMapH = GetGWorldPixMap(theGWorldP);
  732.     LockPixels(offPixMapH);
  733.     CopyBits((BitMapPtr)(*offPixMapH), (BitMapPtr)gDrawPixMapPtr, inOffPos,
  734.              inNewPos, srcCopy, nil);
  735.     UnlockPixels(offPixMapH);
  736.  
  737.     //    Draw union of old and new position to Window.
  738.  
  739.     SetGWorld(aboutBoxWindow, GetMainDevice());
  740.     UnionRect(inCurrPos, inNewPos, &drawRect);
  741.     CopyBits((BitMapPtr)gDrawPixMapPtr, (BitMapPtr)windowPixMapPtr, &drawRect,
  742.              &drawRect, srcCopy, nil);
  743.     
  744.     return;
  745. }
  746.  
  747.  
  748. #pragma mark -
  749. #pragma mark ••• Utils •••
  750.  
  751.  
  752. // returns a rect that is a user item in a DITL
  753.  
  754. void    HsoiGetItemRect( short inItem, Rect *outRect )
  755. {
  756.     DITLHand        theDITL;
  757.     
  758.     theDITL = (DITLHand) GetResource('DITL', rCoolAboutDITL);
  759.     *outRect = (**theDITL).theUserItems[inItem - 1].box;
  760.     
  761.     return;
  762. }
  763.  
  764. // does just what you think...draws a given PICT into a new gworld
  765.  
  766. void HsoiDrawPictIntoNewGWorld(short inPICTid, short inDepth, GWorldPtr *outGWorldP)
  767. {
  768.     PicHandle         thePicture;
  769.     Rect            picFrame;
  770.     GWorldPtr         saveWorld;
  771.     GDHandle         saveDevice;
  772.     OSErr             err;
  773.  
  774.     // get the picture
  775.     
  776.     thePicture = GetPicture(inPICTid);
  777.     
  778.     // get the size/coordinates of the PICTs frame
  779.     
  780.     picFrame = (**thePicture).picFrame;
  781.  
  782.     // create a gworld for the PICT
  783.     
  784.     err = NewGWorld(outGWorldP, inDepth, &picFrame, nil,
  785.                     GetGWorldDevice(gDrawWorldPtr), noNewDevice);
  786.     
  787.     // if we run out of memory, tap temporary memory
  788.     
  789.     if ( err == memFullErr )
  790.         err = NewGWorld( outGWorldP, inDepth, &picFrame, nil,
  791.                     GetGWorldDevice( gDrawWorldPtr), noNewDevice + useTempMem );
  792.     
  793.     // get the old gworld and set the new gworld to our pict's
  794.                     
  795.     GetGWorld(&saveWorld, &saveDevice);
  796.     SetGWorld (*outGWorldP, nil);
  797.     
  798.     // lock the pixels
  799.     
  800.     LockPixels(GetGWorldPixMap(*outGWorldP));
  801.     
  802.     // draw the pict in the new gworld
  803.     
  804.     DrawPicture(thePicture, &picFrame);
  805.     
  806.     // unlock the pixels
  807.     
  808.     UnlockPixels(GetGWorldPixMap(*outGWorldP));
  809.     
  810.     // restore the old gworld
  811.     SetGWorld(saveWorld, saveDevice);
  812.  
  813.     // and dump the pict resource
  814.     
  815.     HsoiForgetResource( (Handle *)&thePicture );
  816.     
  817.     return;
  818. }
  819.  
  820. // eventually, i probably ought to change this to use WASTE instead of TextEdit
  821.  
  822. // this gets our credits (from a 'TEXT' resource) and then draws it into a new gworld
  823.  
  824. void HsoiDrawTextIntoNewGWorld(short inTEXTid, Rect *ioBounds, short inDepth, GWorldPtr *outGWorldP)
  825. {
  826.     Handle             theText;
  827.     TEHandle        theTE;
  828.     StScrpHandle    theStyle;
  829.     GWorldPtr         saveWorld;
  830.     GDHandle         saveDevice;
  831.     OSErr             err;
  832.     
  833.     // Put Text in a TERecord
  834.  
  835.     // set a few text characteristics
  836.         
  837.     TextFont(applFont);    
  838.     TextSize( FONT_SIZE );
  839.     
  840.     // create a text instance to hold our text
  841.      
  842.     theTE = TEStyleNew(ioBounds, ioBounds);
  843.     
  844.     // get our credits text
  845.     
  846.     theText = GetResource('TEXT', inTEXTid);
  847.     
  848.     // get it's associated style
  849.     
  850.     theStyle = (StScrpHandle) GetResource('styl', inTEXTid);
  851.     
  852.     // lock it down
  853.     
  854.     HLock(theText);
  855.     
  856.     // don't show the pen while we draw 
  857.     HidePen();
  858.     
  859.     // insert the TEXT and styl into our TextEdit record
  860.     
  861.     TEStyleInsert(*theText, GetHandleSize(theText), theStyle, theTE);
  862.     
  863.     // show the pen
  864.     
  865.     ShowPen();
  866.     
  867.     // dump the text resource
  868.     
  869.     HsoiForgetResource( &theText );
  870.     
  871.     // dump the styl, if any
  872.     
  873.     if (theStyle != nil)
  874.     {
  875.         HsoiForgetResource( (Handle *)&theStyle );
  876.     }
  877.     
  878.     // set the alignment to a center
  879.     
  880.     TESetAlignment(teJustCenter, theTE);
  881.     
  882.     // recalc the line breaks
  883.     
  884.     TECalText(theTE);
  885.     
  886.     // Determine height of the Text
  887.  
  888.     ioBounds->right = ioBounds->right - ioBounds->left;
  889.     ioBounds->left = ioBounds->top = 0;
  890.     ioBounds->bottom = TEGetHeight((**theTE).nLines, 0, theTE);
  891.     
  892.     // Create new GWorld that is the height of the Text
  893.     err = NewGWorld( outGWorldP, inDepth, ioBounds, nil,
  894.                     GetGWorldDevice( gDrawWorldPtr ), noNewDevice );
  895.     
  896.     // tap ttemp mem if needed
  897.     
  898.     if ( err == memFullErr )
  899.         err = NewGWorld(outGWorldP, inDepth, ioBounds, nil,
  900.                         GetGWorldDevice(gDrawWorldPtr), noNewDevice + useTempMem);
  901.  
  902.     // set up the gworld
  903.     
  904.     GetGWorld(&saveWorld, &saveDevice);
  905.     SetGWorld (*outGWorldP, nil);
  906.     LockPixels(GetGWorldPixMap(*outGWorldP));
  907.     
  908.     // clean out the rect
  909.     
  910.     EraseRect(ioBounds);
  911.  
  912.     // Draw Text inside GWorld
  913.     (**theTE).viewRect = *ioBounds;
  914.     (**theTE).destRect = *ioBounds;
  915.     (**theTE).inPort = (GrafPtr) *outGWorldP;
  916.     
  917.     // update things
  918.     
  919.     TEUpdate(ioBounds, theTE);
  920.     
  921.     // dispose of the TextEdit record
  922.     
  923.     TEDispose(theTE);
  924.     
  925.     InvertRect(ioBounds);            // White letters on black background
  926.  
  927.     // restore the gworlds
  928.     
  929.     UnlockPixels(GetGWorldPixMap(*outGWorldP));
  930.     SetGWorld(saveWorld, saveDevice);
  931.  
  932.     return;
  933. }
  934.  
  935.  
  936.