Source/MainWindow.cp

/*
    File:       MainWindow.cp
 
    Contains:   xxx put contents here xxx
 
    Version:    xxx put version here xxx
 
    Copyright:  © 1999 by Apple Computer, Inc., all rights reserved.
 
    File Ownership:
 
        DRI:                xxx put dri here xxx
 
        Other Contact:      xxx put other contact here xxx
 
        Technology:         xxx put technology here xxx
 
    Writers:
 
        (BWS)   Brent Schorsch
 
    Change History (most recent first):
 
       <SP1>      7/1/99    BWS     first checked in
*/
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ  Includes
 
#include <Controls.h>
#include <FixMath.h>
#include <Fonts.h>
#include <MacWindows.h>
#include <NumberFormatting.h>
#include <QuickDraw.h>
#include <ToolUtils.h>
#include <TextUtils.h>
 
#include <stdio.h>
 
#include "AppShellResources.h"
#include "ISp_SampleResources.h"
#include "MainWindow.h"
#include "ErrorAlert.h"
#include "ISp_Sample.h"
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ  Private Definitions
 
// drawing
#define kButtonsLineStart           40
#define kAxisLineStart              100
 
#define kLineHeight                 12
 
#define kLabelsIndent               60
#define kColumnIndent               150
 
// physics
#define     kMin_Angle          (-180.0)
#define     kMax_Angle          ( 180.0)
 
#define     kThrottleCoef       (   0.01)
#define     kFrictionCoef       (   0.10)
#define     k2ndFrictionCoef    (   0.01)
 
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ  Private Types
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ  Private Variables
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ  Private Functions
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ  Public Variables
 
MainWindow::MainWindow()
{
OSStatus error;
 
    window = GetNewCWindow(kWIND_MainWindow, nil, (WindowPtr) -1L);
            
    ::SetWindowKind(window, userKind);
    ::SetWRefCon(window, (SInt32) this);
 
    CreateRootControl(window, &rootControl);
 
    SetTitle("\pInputSprocket Sample");
    MakeCurrentPort();
 
    Show();
    
    if (!Input_Available())
        ErrorAlert("\pInputSprocket is required."
                    "Place InputSprocketLib, InputSprocketKeyboard, InputSprocketMouse, etc"
                    " in your active SysyemFolder.", 1, true);
    
    error = Input_Initialize();
    if (error)
        ErrorAlert("\pInputSprocket failed to initialize.", error, true);
 
    Input_InitializeState(&mInputState);
}
 
MainWindow::~MainWindow()
{
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Update
 
void
MainWindow::Update(void)
{
GrafPtr     oldPort;
WindowPtr   theWindow = window;
Rect        r;
 
    ::GetPort(&oldPort);
    MakeCurrentPort();
 
    ::BeginUpdate(theWindow);
 
    ::ClipRect(&theWindow->portRect);
    ::EraseRect(&theWindow->portRect);
    
    DrawContents();
    
    r = window->portRect;
    r.left = r.right - 15;
    r.top = r.bottom - 15;
    ::ClipRect(&r);
    ::DrawGrowIcon(theWindow);
 
    ::ClipRect(&theWindow->portRect);
 
    ::EndUpdate(theWindow);
    
    ::SetPort(oldPort);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Grow
 
OSErr
MainWindow::Grow(const Point inWhere)
{
Rect        sizeRect;
long        result;
 
    sizeRect.top = 300;
    sizeRect.left = 450;
    sizeRect.bottom = 440;
    sizeRect.right = 640;
    
    result = ::GrowWindow(window, inWhere, &sizeRect);
 
    if (0 != result)
    {
    GrafPtr oldPort;
    
        ::SizeWindow(window, LoWord(result), HiWord(result), false);
        
        ::GetPort(&oldPort);
        MakeCurrentPort();
        
        ::ClipRect(&window->portRect);
        ::InvalRect(&window->portRect);
        
        ::SetPort(oldPort);
    }
 
    AdjustControlPositions();
 
    return (noErr);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Click
 
OSErr
MainWindow::Click(const Point inWhere, const short inModifiers)
{
#pragma unused (inModifiers)
 
Point           localPoint;
ControlHandle   theControl;
short           thePart;
 
    if (FrontWindow() != window)
        ::SelectWindow(window);
 
    localPoint = inWhere;
    ::GlobalToLocal(&localPoint);
 
    theControl = ::FindControlUnderMouse(localPoint, window, &thePart);
 
    if (nil != theControl)
    {
        (void) ::TrackControl(theControl, localPoint, nil);
    }
 
    return (noErr);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Close
 
OSErr
MainWindow::Close(void)
{
    ::KillControls(window);
    ::DisposeWindow(window);
 
    return (noErr);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Idle
 
void
MainWindow::Idle(void)
{
Boolean gameWasInProgress;
Boolean gameWasPaused;
 
    ShellWindow::Idle();
    
    gameWasInProgress = mInputState.gameInProgress;
    gameWasPaused = mInputState.gamePaused;
    
    ::Input_GetButtonEvents (&mInputState);
    ::Input_PollAxisValues (&mInputState);
    
    if (mInputState.gameInProgress && !gameWasInProgress)
        StartGame ();
    else if (!mInputState.gameInProgress && gameWasInProgress)
        EndGame ();
    else if (mInputState.gamePaused != gameWasPaused)
        TogglePauseGame ();
    
    // do some physics calculations
    mAngleOfRoll = AdjustAngleByAxisInput (mAngleOfRoll, mInputState.rollInput);
    mAngleOfRoll = AdjustAngleByFixedDelta (mAngleOfRoll, mInputState.deltaRoll);
    
    mAngleOfPitch = AdjustAngleByAxisInput (mAngleOfPitch, mInputState.pitchInput);;
    mAngleOfPitch = AdjustAngleByFixedDelta (mAngleOfPitch, mInputState.deltaPitch);;
 
    mAngleOfYaw = AdjustAngleByAxisInput (mAngleOfYaw, mInputState.yawInput);
    mAngleOfYaw = AdjustAngleByFixedDelta (mAngleOfYaw, mInputState.deltaYaw);
 
    mVelocity = mVelocity + (kThrottleCoef * mInputState.throttleInput) - kFrictionCoef - (k2ndFrictionCoef * mVelocity);
    if (mVelocity < 0) mVelocity = 0;
    
    DrawValues();
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Menu
 
Boolean
MainWindow::Menu(const UInt32 inMenuCommand, const short inModifiers)
{
#pragma unused (inModifiers)
 
Boolean     handled = true;
 
    switch (inMenuCommand)
    {
        case kMenuCMD_StartGame:
            StartGame ();
            break;
            
        case kMenuCMD_ConfigureInput:
            Input_ShowConfigureDialog();
            break;
        
        default:
            handled = false;
            break;
    }
 
 
    return (handled);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Suspend
 
void
MainWindow::Suspend(void)
{
    Input_Suspend ();
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::Resume
 
void
MainWindow::Resume(void)
{
    Input_Resume ();
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::DrawContents
 
void
MainWindow::DrawContents(void)
{
GrafPtr oldPort;
Rect    r;
 
    ::GetPort(&oldPort);
    MakeCurrentPort();
    
    ::DrawControls(window);
    
    ::TextFace(bold);
    ::TextFont(kFontIDGeneva);
    ::TextSize(9);
    
    //¥ erase the game in progress/paused area
    r.left = 0;
    r.right = Width();
    r.top = 0;
    r.bottom = 15;
    EraseRect (&r);
    
    //¥ draw the game in progress/paused area
    if (!mInputState.gameInProgress)
        DrawStringCentered("\pPress Start or select New Game to start", kLineHeight);
    else
    {
        if (mInputState.gamePaused)
            DrawStringCentered("\pPaused", kLineHeight);
        else
            DrawStringCentered("\pGame in progress, MacOS cursor and menus disabled", kLineHeight);
    }
    
    //¥ draw button captions
                                                                        // skip line for 'Firing Weapon' caption
    DrawStringRightJustified ("\pShots Fired Weapon:",  kLabelsIndent * 2, kButtonsLineStart + (kLineHeight * 1), 0);
    DrawStringRightJustified ("\pCurrent Weapon:",      kLabelsIndent * 2, kButtonsLineStart + (kLineHeight * 2), 0);
 
    //¥ draw axis captions
    DrawStringRightJustified ("\pRoll:",        kLabelsIndent, kAxisLineStart + (kLineHeight * 0), 0);
    DrawStringRightJustified ("\pPitch:",       kLabelsIndent, kAxisLineStart + (kLineHeight * 1), 0);
    DrawStringRightJustified ("\pYaw:",         kLabelsIndent, kAxisLineStart + (kLineHeight * 2), 0);
    DrawStringRightJustified ("\pThrottle:",    kLabelsIndent, kAxisLineStart + (kLineHeight * 3), 0);
    
    DrawStringRightJustified ("\pRoll Delta:",  kColumnIndent + kLabelsIndent, kAxisLineStart + (kLineHeight * 0), 0);
    DrawStringRightJustified ("\pPitch Delta:", kColumnIndent + kLabelsIndent, kAxisLineStart + (kLineHeight * 1), 0);
    DrawStringRightJustified ("\pYaw Delta:",   kColumnIndent + kLabelsIndent, kAxisLineStart + (kLineHeight * 2), 0);
 
    DrawStringRightJustified ("\pAngle of Roll:",   (kColumnIndent * 2) + kLabelsIndent, kAxisLineStart + (kLineHeight * 0), 0);
    DrawStringRightJustified ("\pAngle of Pitch:",  (kColumnIndent * 2) + kLabelsIndent, kAxisLineStart + (kLineHeight * 1), 0);
    DrawStringRightJustified ("\pAngle of Yaw:",    (kColumnIndent * 2) + kLabelsIndent, kAxisLineStart + (kLineHeight * 2), 0);
    DrawStringRightJustified ("\pVelocity:",        (kColumnIndent * 2) + kLabelsIndent, kAxisLineStart + (kLineHeight * 3), 0);
    
 
    DrawValues();
 
    ::SetPort(oldPort);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::DrawValues
 
void
MainWindow::DrawValues(void)
{
GrafPtr oldPort;
Str255  string;
 
    ::GetPort(&oldPort);
    MakeCurrentPort();
    
    ::TextMode(srcCopy);
    
    if (mInputState.gameInProgress)
    {
        // Firing weapon
        SInt16  numbersIndent = (kLabelsIndent * 2) + 3;
        
        if (mInputState.fireWeaponState)
            DrawStringRightJustified ("\pFiring _Now_", kLabelsIndent * 2, kButtonsLineStart + (kLineHeight * 0), 100);
        else
            DrawStringRightJustified ("\p", kLabelsIndent * 2, kButtonsLineStart + (kLineHeight * 0), 100);
        
        ::NumToString (mInputState.fireWeaponCount, string);
        DrawStringLeftJustified (string,                numbersIndent, kButtonsLineStart + (kLineHeight * 1), 20);
        
        GetWeaponString (mInputState.currentWeapon, string);
        DrawStringLeftJustified (string,                numbersIndent, kButtonsLineStart + (kLineHeight * 2), 150);
 
        // axis values
        numbersIndent -= kLabelsIndent;
        
        ::NumToString (mInputState.rollInput, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 0), 30);
        
        ::NumToString (mInputState.pitchInput, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 1), 30);
 
        ::NumToString (mInputState.yawInput, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 2), 30);
 
        ::NumToString (mInputState.throttleInput, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 3), 30);
        
        // delta values
        numbersIndent += kColumnIndent;
        
        FixedToString (mInputState.deltaRoll, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 0), 30);
        
        FixedToString (mInputState.deltaPitch, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 1), 30);
 
        FixedToString (mInputState.deltaYaw, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 2), 30);
 
        // physics values
        numbersIndent += kColumnIndent;
 
        FloatToString (mAngleOfRoll, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 0), 30);
        
        FloatToString (mAngleOfPitch, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 1), 30);
 
        FloatToString (mAngleOfYaw, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 2), 30);
 
        FloatToString (mVelocity, string);
        DrawStringLeftJustified (string, numbersIndent, kAxisLineStart + (kLineHeight * 3), 30);
    }
    
    ::TextMode(srcOr);
 
    ::SetPort(oldPort);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::AdjustControlPositions
 
void
MainWindow::AdjustControlPositions(void)
{
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::StartGame
 
void
MainWindow::StartGame(void)
{
    Input_InitializeState(&mInputState);
 
    mInputState.gameInProgress = true;
    mInputState.gamePaused = false;
    
    Input_DisableKeyboardForTyping();
    Input_DisableMouseForCursor();
    
    ::HideCursor();
    
    mAngleOfRoll = 0.0;
    mAngleOfPitch = 0.0;
    mAngleOfYaw = 0.0;
    mVelocity = 0.0;
 
    DrawContents();
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::EndGame
 
void
MainWindow::EndGame(void)
{
    mInputState.gameInProgress = false;
    mInputState.gamePaused = false;
    
    Input_EnableKeyboardForTyping();
    Input_EnableMouseForCursor();
 
    ::InitCursor();
 
    DrawContents();
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::TogglePauseGame
 
void
MainWindow::TogglePauseGame(void)
{
    if (mInputState.gamePaused)
    {
        Input_EnableKeyboardForTyping();
        Input_EnableMouseForCursor();
 
        ::ShowCursor();
    }
    else
    {
        Input_DisableKeyboardForTyping();
        Input_DisableMouseForCursor();
 
        ::HideCursor();
    }
    
    DrawContents();
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::GetWeaponString
void
MainWindow::GetWeaponString (SInt16 inWeapon, StringPtr ioString)
{
    GetIndString (ioString, kSTRn_WeaponNames, inWeapon + 1);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::DrawStringCentered
void
MainWindow::DrawStringCentered (StringPtr string, SInt16 height)
{
UInt32  width;
 
    width = StringWidth(string);
    ::MoveTo((Width() / 2) - (width / 2), height);
    ::DrawString(string);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::DrawStringLeftJustified
void
MainWindow::DrawStringLeftJustified (StringPtr string, SInt16 indent, SInt16 height, SInt16 eraseSize)
{
UInt32  width;
Rect    r;
 
    width = StringWidth(string);
    
    if (eraseSize)
    {
        r.left = indent + width;
        r.right = r.left + eraseSize;
        r.top = height - 10;
        r.bottom = height + 2;
        EraseRect (&r);
    }
    
    ::MoveTo(indent, height);
    ::DrawString(string);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::DrawStringRightJustified
void
MainWindow::DrawStringRightJustified (StringPtr string, SInt16 indent, SInt16 height, SInt16 eraseSize)
{
UInt32  width;
Rect    r;
 
    width = StringWidth(string);
 
    if (eraseSize)
    {
        r.right = indent - width;
        r.left = r.right - eraseSize;
        r.top = height - 10;
        r.bottom = height + 2;
        EraseRect (&r);
    }
    
    ::MoveTo(indent - width, height);
    ::DrawString(string);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::FixedToString
void
MainWindow::FixedToString (Fixed inFixed, StringPtr ioString)
{
float   inches = Fix2X (inFixed);
 
    sprintf((char *) ioString, "%01.02f", inches * 100.0);
    c2pstr((char *) ioString);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::FloatToString
void
MainWindow::FloatToString (float inFloat, StringPtr ioString)
{
    sprintf((char *) ioString, "%01.01f", inFloat);
    c2pstr((char *) ioString);
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::AdjustAngleByAxisInput
float
MainWindow::AdjustAngleByAxisInput (float inCurrentAngle, SInt32 inAxisValue)
{
    float   newAngle = inCurrentAngle + (inAxisValue / (kMax_Roll * 0.5));
    
    while (newAngle < kMin_Angle)
        newAngle += (kMax_Angle - kMin_Angle);
 
    while (newAngle > kMax_Angle)
        newAngle -= (kMax_Angle - kMin_Angle);
    
    return newAngle;
}
 
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ    MainWindow::AdjustAngleByFixedDelta
float
MainWindow::AdjustAngleByFixedDelta (float inCurrentAngle, Fixed inDeltaValue)
{
    float   newAngle = inCurrentAngle + (Fix2X(inDeltaValue) * 50.0);
    
    while (newAngle < kMin_Angle)
        newAngle += (kMax_Angle - kMin_Angle);
 
    while (newAngle > kMax_Angle)
        newAngle -= (kMax_Angle - kMin_Angle);
    
    return newAngle;
}