Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
DZInput.c
/* |
File: DZInput.c |
Contains: xxx put contents here xxx |
Version: xxx put version here xxx |
Copyright: © 1998 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 |
(sjb) Steve Bollinger |
Change History (most recent first): |
<SP15> 10/20/98 BWS Pause and Quit are now separate needs |
<14> 6/18/98 sjb InputSprocket.h comes from <> place |
*/ |
/* |
* File: DZInput.c |
* |
* Contents: Handles input devices. |
* |
* Copyright © 1996 Apple Computer, Inc. |
*/ |
#include <TextUtils.h> |
#define USE_OLD_INPUT_SPROCKET_LABELS 0 |
#define USE_OLD_ISPNEED_STRUCT 0 |
#include <InputSprocket.h> |
#include "DZGame.h" |
#include "DZInput.h" |
#include "DZResource.h" |
#define USE_MOUSE_AND_KEYBOARD 1 |
#define ISpSymmetricAxisToFloat(axis) ((((float) axis) - kISpAxisMiddle) / (kISpAxisMaximum-kISpAxisMiddle)) |
#define ISpAsymmetricAxisToFloat(axis) (((float) axis) / (kISpAxisMaximum)) |
/* |
enum { |
kElement_Fire, |
kElement_Pause, |
kElement_ShowHUD, |
kElement_ShowFPS, |
kElement_Turn, |
kElement_COUNT |
}; |
*/ |
enum |
{ |
kNeed_Fire, |
kNeed_Roll, |
kNeed_Pitch, |
kNeed_Throttle, |
kNeed_ThrottleUp, |
kNeed_ThrottleDown, |
kNeed_ThrottleFull, |
kNeed_ThrottleZero, |
kNeed_InertialDampers, |
kNeed_Yaw, |
kNeed_YawLeft, |
kNeed_YawCenter, |
kNeed_YawRight, |
kNeed_ShowHUD, |
kNeed_ShowFPS, |
kNeed_ShowThrottle, |
kNeed_ShowVelocity, |
kNeed_InstantStop, |
kNeed_Pause, |
kNeed_COUNT |
}; |
#define kNeedsVersion 1 |
static Boolean gInputActive = false; |
static ISpElementListReference gInputEventList = NULL; |
static ISpElementListReference gInputHoldDownEventList = NULL; |
static ISpElementListReference gInputYawEventList = NULL; |
static ISpElementListReference gInputThrottleEventList = NULL; |
static ISpElementReference gInputElement[kNeed_COUNT] = {NULL, NULL, NULL, NULL, NULL}; |
/* ============================================================================= |
* Input_Init (external) |
* |
* Initializes the Input stuff. |
* ========================================================================== */ |
void Input_Init( |
void) |
{ |
UInt32 itr; |
ISpNeed needs[kNeed_COUNT] = |
{ |
{ "\pFire", kIconSuiteID_Fire, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_Btn_Fire, |
0, 0, 0, 0 |
}, |
{ "\pRoll", kIconSuiteID_Roll, 0, 0, |
kISpElementKind_Axis, |
kISpElementLabel_Axis_Roll, |
0, 0, 0, 0 |
}, |
{ "\pPitch", kIconSuiteID_Pitch, 0, 0, |
kISpElementKind_Axis, |
kISpElementLabel_Axis_Pitch, |
0, 0, 0, 0 |
}, |
{ "\pThrottle", kIconSuiteID_Throttle, 0, 1, |
kISpElementKind_Axis, |
kISpElementLabel_Axis_Throttle, |
kISpNeedFlag_Axis_AlreadyButton | kISpNeedFlag_Axis_Asymetric, 0, 0, 0 |
}, |
{ "\pIncrease Throttle", kIconSuiteID_ThrottleUp, 0, 1, |
kISpElementKind_Button, |
kISpElementLabel_None, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pDecrease Throttle", kIconSuiteID_ThrottleDown, 0, 1, |
kISpElementKind_Button, |
kISpElementLabel_None, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pThrottle Max", kIconSuiteID_ThrottleMax, 0, 1, |
kISpElementKind_Button, |
kISpElementLabel_None, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pThrottle Min", kIconSuiteID_ThrottleMin, 0, 1, |
kISpElementKind_Button, |
kISpElementLabel_None, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pInertial Dampers", kIconSuiteID_InertialDampers, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
0, 0, 0, 0 |
}, |
{ "\pRudder", kIconSuiteID_Rudder, 0, 2, |
kISpElementKind_Axis, |
kISpElementLabel_Axis_Rudder, |
kISpNeedFlag_Axis_AlreadyButton, 0, 0, 0 |
}, |
{ "\pYaw Left", kIconSuiteID_RudderLeft, 0, 2, |
kISpElementKind_Button, |
kISpElementLabel_Btn_LookLeft, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pYaw Center", kIconSuiteID_RudderCenter, 0, 2, |
kISpElementKind_Button, |
kISpElementLabel_None, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pYaw Right", kIconSuiteID_RudderRight, 0, 2, |
kISpElementKind_Button, |
kISpElementLabel_Btn_LookRight, |
kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0 |
}, |
{ "\pShow HUD", kIconSuiteID_ShowHUD, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
0, 0, 0, 0 |
}, |
{ "\pShow FPS", kIconSuiteID_ShowFPS, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
0, 0, 0, 0 |
}, |
{ "\pShow Throttle", kIconSuiteID_ShowThrottle, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
0, 0, 0, 0 |
}, |
{ "\pShow Velocity", kIconSuiteID_ShowVelocity, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
0, 0, 0, 0 |
}, |
{ "\pInstant Stop", kIconSuiteID_InstantStop, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
0, 0, 0, 0 |
}, |
{ "\pPause", kIconSuiteID_Pause, 0, 0, |
kISpElementKind_Button, |
kISpElementLabel_Btn_StartPause, |
0, 0, 0, 0 |
} |
}; |
// Get the names for the needs |
for (itr = 0; itr < kNeed_COUNT; itr++) |
GetIndString(needs[itr].name, kStrListID_NeedsNames, itr+1); |
#if USE_MOUSE_AND_KEYBOARD |
// Enable the mouse |
ISpDevices_ActivateClass (kISpDeviceClass_Mouse); |
// Enable the keyboard |
ISpDevices_ActivateClass (kISpDeviceClass_Keyboard); |
#endif |
// Set our virtual elements |
ISpElement_NewVirtualFromNeeds(kNeed_COUNT, needs, gInputElement, 0); |
// Autoconfigure our virtual elements based on our needs |
ISpInit(kNeed_COUNT, needs, gInputElement, ' dz ', kNeedsVersion, 0, kSetListID, 0); |
// Build two lists of elements, which we'll poll for events |
// the 'hold down' list reports both up and down events |
ISpElementList_New(0, NULL, &gInputEventList, 0); |
ISpElementList_New(0, NULL, &gInputHoldDownEventList, 0); |
// Add the virtual elements one at a time so we can assign a refcon |
ISpElementList_AddElements(gInputHoldDownEventList, kInputEvent_Fire_On,1, &gInputElement[kNeed_Fire]); |
ISpElementList_AddElements(gInputHoldDownEventList, kInputEvent_InertialDampers_On, |
1, &gInputElement[kNeed_InertialDampers]); |
ISpElementList_AddElements(gInputEventList, kInputEvent_InstantStop, 1, &gInputElement[kNeed_InstantStop]); |
ISpElementList_AddElements(gInputEventList, kInputEvent_ShowHUD, 1, &gInputElement[kNeed_ShowHUD]); |
ISpElementList_AddElements(gInputEventList, kInputEvent_ShowFPS, 1, &gInputElement[kNeed_ShowFPS]); |
ISpElementList_AddElements(gInputEventList, kInputEvent_ShowThrottle, 1, &gInputElement[kNeed_ShowThrottle]); |
ISpElementList_AddElements(gInputEventList, kInputEvent_ShowVelocity, 1, &gInputElement[kNeed_ShowVelocity]); |
ISpElementList_AddElements(gInputEventList, kInputEvent_Pause, 1, &gInputElement[kNeed_Pause]); |
// Build our list of elements used for the rudder (yaw) when from buttons |
ISpElementList_New(0, NULL, &gInputYawEventList, 0); |
// Add the virtual elements one at a time so we can assign a refcon |
ISpElementList_AddElements(gInputYawEventList, kNeed_YawLeft, 1, &gInputElement[kNeed_YawLeft]); |
ISpElementList_AddElements(gInputYawEventList, kNeed_YawCenter, 1, &gInputElement[kNeed_YawCenter]); |
ISpElementList_AddElements(gInputYawEventList, kNeed_YawRight, 1, &gInputElement[kNeed_YawRight]); |
// Build our list of elements used for the throttle when from buttons |
ISpElementList_New(0, NULL, &gInputThrottleEventList, 0); |
// Add the virtual elements one at a time so we can assign a refcon |
ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleUp, 1, &gInputElement[kNeed_ThrottleUp]); |
ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleDown, 1, &gInputElement[kNeed_ThrottleDown]); |
ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleFull, 1, &gInputElement[kNeed_ThrottleFull]); |
ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleZero, 1, &gInputElement[kNeed_ThrottleZero]); |
// Start off suspended (because the game is stopped) |
ISpSuspend(); |
} |
/* ============================================================================= |
* Input_Exit (external) |
* |
* Prepares for exit. |
* ========================================================================== */ |
void Input_Exit( |
void) |
{ |
if (gInputActive) |
{ |
Input_Activate(false); |
} |
if (gInputEventList != NULL) |
{ |
ISpElementList_Dispose(gInputEventList); |
gInputEventList = NULL; |
} |
if (gInputHoldDownEventList != NULL) |
{ |
ISpElementList_Dispose(gInputHoldDownEventList); |
gInputHoldDownEventList = NULL; |
} |
ISpStop(); |
ISpElement_DisposeVirtual(kNeed_COUNT, gInputElement); |
} |
/* ============================================================================= |
* Input_Configure (external) |
* |
* Show the configuration dialog. |
* ========================================================================== */ |
void Input_Configure( |
void) |
{ |
ISpConfigure(NULL); |
} |
#if 0 |
/* ============================================================================= |
* Input_GetState (external) |
* |
* This routine handles the elements that are polled. It returns in outXTurn |
* and outYTurn the "turn" controls in the ±1 range. |
* ========================================================================== */ |
void Input_GetState( |
float* outXTurn, |
float* outYTurn) |
{ |
ISpMovementData movementData; |
double xTurn = 0.0; |
double yTurn = 0.0; |
if (gInputActive) |
{ |
// Get the data |
ISpElement_GetComplexState( |
gInputElement[kNeed_Turn], |
sizeof(ISpMovementData), |
&movementData); |
// Turn 'em into ±1 float range |
xTurn = movementData.xAxis; |
xTurn -= kISpAxisMiddle; |
xTurn /= kISpAxisMaximum-kISpAxisMiddle; |
yTurn = movementData.yAxis; |
yTurn -= kISpAxisMiddle; |
yTurn /= kISpAxisMaximum-kISpAxisMiddle; |
yTurn *= -1; // reverse axis |
} |
// Return the values |
*outXTurn = xTurn; |
*outYTurn = yTurn; |
} |
#endif |
float Input_GetRoll (void) |
{ |
ISpAxisData axisValue = kISpAxisMiddle; |
(void) ISpElement_GetSimpleState(gInputElement[kNeed_Roll], &axisValue); |
return ISpSymmetricAxisToFloat (axisValue); |
} |
float Input_GetPitch (void) |
{ |
ISpAxisData axisValue = kISpAxisMiddle; |
(void) ISpElement_GetSimpleState(gInputElement[kNeed_Pitch], &axisValue); |
return (-1.0 * ISpSymmetricAxisToFloat (axisValue)); |
} |
float Input_GetYaw (void) |
{ |
static float gYawValue = 0.0; |
static Boolean gYawInitalized = false; |
float yawValue = gYawValue; |
OSStatus error = noErr; |
ISpAxisData axisValue; |
Boolean wasEvent; |
ISpElementEvent event; |
// should probably put the initialization check somewhere else, so does not do it every time |
if (!gYawInitalized) |
{ |
(void) ISpElement_GetSimpleState(gInputElement[kNeed_Yaw], &axisValue); |
gYawValue = ISpSymmetricAxisToFloat (axisValue); |
gYawInitalized = true; |
} |
// we check the axis, to see if IT was moved, if so, we use that value |
wasEvent = false; |
error = ISpElement_GetNextEvent (gInputElement[kNeed_Yaw], sizeof (event), &event, &wasEvent); |
if (!error && wasEvent) |
{ |
error = ISpElement_GetSimpleState(gInputElement[kNeed_Yaw], &axisValue); |
if (!error) yawValue = ISpSymmetricAxisToFloat (axisValue); |
ISpElement_Flush(gInputElement[kNeed_Yaw]); |
} |
else do |
{ |
error = ISpElementList_GetNextEvent (gInputYawEventList, sizeof (event), &event, &wasEvent); |
// only process valid keydown events (all the yaw events ignore button ups) |
if (wasEvent && !error && (event.data == kISpButtonDown)) |
{ |
UInt32 keyFunction = event.refCon; // because we set it this way |
switch (keyFunction) |
{ |
case kNeed_YawLeft: |
yawValue -= 0.1; |
if (yawValue < -1.0) yawValue = -1.0; |
break; |
case kNeed_YawCenter: |
yawValue = 0.0; |
break; |
case kNeed_YawRight: |
yawValue += 0.1; |
if (yawValue > 1.0) yawValue = 1.0; |
break; |
} |
} |
} |
while (wasEvent && !error); |
gYawValue = yawValue; |
return yawValue; |
} |
float Input_GetThrottle (void) |
{ |
static float gThrottleValue = 0.0; |
static Boolean gThrottleInitialized = false; |
float throttleValue = gThrottleValue; |
OSStatus error = noErr; |
ISpAxisData axisValue; |
Boolean wasEvent; |
ISpElementEvent event; |
// should probably put the initialization check somewhere else, so does not do it every time |
if (!gThrottleInitialized) |
{ |
(void) ISpElement_GetSimpleState(gInputElement[kNeed_Throttle], &axisValue); |
gThrottleValue = ISpAsymmetricAxisToFloat (axisValue); |
gThrottleInitialized = true; |
} |
// we check the axis, to see if IT was moved, if so, we use that value |
wasEvent = false; |
error = ISpElement_GetNextEvent (gInputElement[kNeed_Throttle], sizeof (event), &event, &wasEvent); |
if (!error && wasEvent) |
{ |
error = ISpElement_GetSimpleState(gInputElement[kNeed_Throttle], &axisValue); |
if (!error) throttleValue = ISpAsymmetricAxisToFloat (axisValue); |
ISpElement_Flush(gInputElement[kNeed_Throttle]); |
} |
else do |
{ |
error = ISpElementList_GetNextEvent (gInputThrottleEventList, sizeof (event), &event, &wasEvent); |
// only process valid keydown events (all the throttle events ignore button ups) |
if (wasEvent && !error && (event.data == kISpButtonDown)) |
{ |
UInt32 keyFunction = event.refCon; // because we set it this way |
switch (keyFunction) |
{ |
case kNeed_ThrottleUp: |
throttleValue += 0.05; |
if (throttleValue > 1.0) throttleValue = 1.0; |
break; |
case kNeed_ThrottleDown: |
throttleValue -= 0.05; |
if (throttleValue < 0.0) throttleValue = 0.0; |
break; |
case kNeed_ThrottleFull: |
throttleValue = 1.0; |
break; |
case kNeed_ThrottleZero: |
throttleValue = 0.0; |
break; |
} |
} |
} |
while (wasEvent && !error); |
gThrottleValue = throttleValue; |
return throttleValue; |
} |
/* ============================================================================= |
* Input_GetEvent (external) |
* |
* This routine handles the elements that are event-based. It returns an |
* event code indicating which button has gone down. Note that we ignore |
* button-up transitions. Should be called repeatedly until it return |
* kInputEvent_None. |
* ========================================================================== */ |
TInputEvent Input_GetEvent( |
void) |
{ |
OSErr err; |
TInputEvent result = kInputEvent_None; |
ISpElementEvent event; |
Boolean gotEvent; |
if (gInputActive) |
{ |
err = ISpElementList_GetNextEvent(gInputHoldDownEventList, sizeof(event), &event, &gotEvent); |
if (err == noErr && gotEvent) |
{ |
result = (TInputEvent) event.refCon; |
if (event.data == kISpButtonUp) |
result += 1; // Note: we rely on off being on+1 (ie kInputEvent_InertialDampers_Off == kInputEvent_InertialDampers_On + 1) |
} |
else |
{ |
err = ISpElementList_GetNextEvent(gInputEventList, sizeof(event), &event, &gotEvent); |
if (err == noErr && gotEvent && event.data == kISpButtonDown) |
result = (TInputEvent) event.refCon; |
} |
} |
return result; |
} |
/* ============================================================================= |
* Input_Activate (external) |
* |
* On deactivation, we suspend InputSprocket. On activation we resume it and |
* flush the event queue. We only allow activation when the game is in "Play" |
* state. |
* ========================================================================== */ |
void Input_Activate( |
Boolean inActivate) |
{ |
Boolean doActivate; |
doActivate = inActivate; |
if (doActivate && Game_GetState() != kGameState_Playing) |
{ |
doActivate = false; |
} |
if (gInputActive != doActivate) |
{ |
gInputActive = doActivate; |
if (gInputActive) |
{ |
#if USE_MOUSE_AND_KEYBOARD |
HideCursor(); |
#endif |
ISpResume(); |
ISpElementList_Flush(gInputEventList); |
} |
else |
{ |
ISpSuspend(); |
#if USE_MOUSE_AND_KEYBOARD |
ShowCursor(); |
#endif |
} |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14