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.
Source/EventHandler.c
/* |
File: EventHandler.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: |
(cjd) Chris DeSalvo |
(sjb) Steve Bollinger |
(BWS) Brent Schorsch |
Change History (most recent first): |
<SP21> 10/20/98 BWS Pause and Quit are now separate needs |
<20> 7/1/98 cjd Added CPU load axis to InputSprocket data set |
<19> 6/18/98 sjb InputSprocket.h comes from <> place |
<18> 6/12/98 BWS Changed to use InputSprocket 68k |
*/ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ |
//¥ Copyright © 1996 Apple Computer, Inc., All Rights Reserved |
//¥ |
//¥ |
//¥ You may incorporate this sample code into your applications without |
//¥ restriction, though the sample code has been provided "AS IS" and the |
//¥ responsibility for its operation is 100% yours. However, what you are |
//¥ not permitted to do is to redistribute the source as "DSC Sample Code" |
//¥ after having made changes. If you're going to re-distribute the source, |
//¥ we require that you make it clear in the source that the code was |
//¥ descended from Apple Sample Code, but that you've made changes. |
//¥ |
//¥ Authors: |
//¥ Chris De Salvo |
//¥ Michael Evans |
//¥ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ ------------------------------ Includes |
#include <DiskInit.h> |
#include <ToolUtils.h> |
#define USE_OLD_ISPNEED_STRUCT 0 |
#define USE_OLD_INPUT_SPROCKET_LABELS 0 |
#include <DrawSprocket.h> |
#include <InputSprocket.h> |
#include "ErrorHandler.h" |
#include "EventHandler.h" |
#include "Graphics.h" |
#include "MenuHandler.h" |
#include "SprocketInvaders.h" |
//¥ ------------------------------ Private Definitions |
//¥ ------------------------------ Private Types |
//¥ ------------------------------ Private Variables |
static SInt32 gEventTime; |
static SInt16 gSleepTime; |
//¥ ------------------------------ Private Functions |
static void EventDispatch(EventRecord *theEvent); |
static Boolean DefaultMouseDown(EventRecord *theEvent); |
static Boolean DefaultKeyDown(EventRecord *theEvent); |
static Boolean DoDiskEvent(EventRecord *theEvent); |
static void DoSuspend(void); |
//¥ ------------------------------ Public Variables |
Boolean gDone = false; |
SInt32 gDeltaTime; |
EventHandlerSet gEventHandlers; |
ISpElementReference gInputElements[numInputs]; |
GameKeys gGameKeys; |
//¥ -------------------- EventInit |
short |
EventInit(void) |
{ |
SInt16 modifiers = 0; |
EventRecord dummy; |
OSStatus theError; |
//¥ This structure defines the input needs that we'll be requesting from InputSprocket |
ISpNeed myNeeds[numInputs] = |
{ |
{ |
"\pPlayer 1 Movement", |
200, |
1, |
0, |
kISpElementKind_Axis, |
kISpElementLabel_Axis_XAxis, |
0, |
0, |
0, |
0 |
}, |
{ |
"\pPlayer 1 Fire", |
201, |
1, |
0, |
kISpElementKind_Button, |
kISpElementLabel_Btn_Fire, |
0, |
0, |
0, |
0 |
}, |
{ |
"\pPlayer 2 Movement", |
203, |
2, |
0, |
kISpElementKind_Axis, |
kISpElementLabel_Axis_XAxis, |
0, |
0, |
0, |
0 |
}, |
{ |
"\pPlayer 2 Fire", |
204, |
2, |
0, |
kISpElementKind_Button, |
kISpElementLabel_Btn_Fire, |
0, |
0, |
0, |
0 |
}, |
{ |
"\pAbort Game", |
202, |
0, |
0, |
kISpElementKind_Button, |
kISpElementLabel_Btn_Quit, |
0, |
0, |
0, |
0 |
}, |
{ |
"\pToggle Sound", |
205, |
0, |
0, |
kISpElementKind_Button, |
kISpElementLabel_None, |
kISpNeedFlag_Utility, |
0, |
0, |
0 |
}, |
{ |
"\pSoundSprocket CPU Load", |
206, |
0, |
0, |
kISpElementKind_Axis, |
kISpElementLabel_None, |
0, |
0, |
0, |
0 |
} |
}; |
EventAvail(everyEvent, &dummy); |
modifiers |= dummy.modifiers; |
EventAvail(everyEvent, &dummy); |
modifiers |= dummy.modifiers; |
EventAvail(everyEvent, &dummy); |
modifiers |= dummy.modifiers; |
RegisterEventHandlers(DefaultKeyDown, DefaultKeyDown, DefaultMouseDown, nil, nil); |
gEventHandlers.diskHandler = DoDiskEvent; |
//¥ This sets up how often we'll call WaitNextEvent() in out event loop. |
//¥ WNE is still emulated so it's sort of a time waster if you call it too often. |
//¥ So, we check DblTime which is the user-selected double-click speed. We make sure |
//¥ that we check inputs at least often enough to notice double-clicks. |
gEventTime = GetDblTime(); |
gEventTime /= 2; |
//¥ This is how much time we'll give to background apps when we're not actively playing |
//¥ a game. |
gSleepTime = 32767; |
//¥ Setup the input sprocket elements |
theError = ISpElement_NewVirtualFromNeeds(numInputs, myNeeds, gInputElements, 0); |
if (theError) |
FatalError("Could not create ISp virtual controls from needs."); |
//¥ Init InputSprocket and tell it our needs |
theError = ISpInit(numInputs, myNeeds, gInputElements, 'SInv', '0002', 0, 128, 0); |
if (theError) |
FatalError("Could not initialize ISp."); |
//¥ Turn on the keyboard and mouse handlers |
ISpDevices_ActivateClass (kISpDeviceClass_Keyboard); |
ISpDevices_ActivateClass (kISpDeviceClass_Mouse); |
ISpDevices_ActivateClass (kISpDeviceClass_SpeechRecognition); |
ISpSuspend (); |
return (modifiers); |
} |
//¥ -------------------- EventLoop |
void |
EventLoop(void) |
{ |
EventRecord theEvent; |
static SInt32 lastTime = 0L; |
SInt32 thisTime; |
Boolean wasProcessed; |
while (false == gDone) |
{ |
thisTime = TickCount(); |
//¥ We don't call WNE while we're playing the game |
if (false == gGameInProgress) |
{ |
if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, nil)) |
{ |
//¥ See if DrawSprocket wants to handle this event |
DSpProcessEvent(&theEvent, &wasProcessed); |
//¥ If DSp punted then we process the event |
if (false == wasProcessed) |
EventDispatch(&theEvent); |
} |
else |
{ |
//¥ Run any idle tasks |
if (gEventHandlers.idleHandler) |
{ |
(*gEventHandlers.idleHandler)(&theEvent); |
} |
} |
} |
//¥ gDeltaTime tells the game engine how much time has passed since the last |
//¥ game loop. |
if (lastTime > 0) |
gDeltaTime = thisTime - lastTime; |
//¥ We must tell it that at least SOME time has passed. |
if (gDeltaTime < 1) |
gDeltaTime = 1; |
if (gGameInProgress) |
{ |
ISpTickle(); |
GameLoop(); |
} |
lastTime = TickCount(); |
} |
} |
//¥ -------------------- EventDispatch |
static void |
EventDispatch(EventRecord *theEvent) |
{ |
switch (theEvent->what) |
{ |
case mouseDown: |
if (gEventHandlers.clickHandler != nil) |
if ((*gEventHandlers.clickHandler)(theEvent)) |
{ |
break; |
} |
DefaultMouseDown(theEvent); |
break; |
case keyDown: |
if (gEventHandlers.keyHandler != nil) |
if ((*gEventHandlers.keyHandler)(theEvent)) |
{ |
break; |
} |
DefaultKeyDown(theEvent); |
break; |
case autoKey: |
if (gEventHandlers.autoKeyHandler != nil) |
if ((*gEventHandlers.autoKeyHandler)(theEvent)) |
{ |
break; |
} |
DefaultKeyDown(theEvent); |
break; |
case updateEvt: |
if (gEventHandlers.updateHandler != nil) |
{ |
if ((*gEventHandlers.updateHandler)(theEvent)) |
{ |
} |
} |
BeginUpdate((WindowRef) theEvent->message); |
GraphicsDoUpdateEvent(); |
EndUpdate((WindowRef) theEvent->message); |
break; |
case diskEvt: |
if (gEventHandlers.diskHandler != nil) |
(*gEventHandlers.diskHandler)(theEvent); |
break; |
case osEvt: |
if (theEvent->message & 0x01000000) //¥ Suspend/resume event |
{ |
if (theEvent->message & 0x00000001) //¥ Resume |
{ |
} |
else |
{ |
DoSuspend(); //¥ Suspend |
} |
} |
break; |
case kHighLevelEvent: |
AEProcessAppleEvent(theEvent); |
break; |
} |
} |
//¥ ------------------------------ DefaultMouseDown |
static Boolean |
DefaultMouseDown(EventRecord *theEvent) |
{ |
SInt16 whatPart; |
SInt32 menuResult; |
WindowRef whichWindow; |
whatPart = FindWindow(theEvent->where, &whichWindow); |
switch (whatPart) |
{ |
case inGoAway: |
break; |
case inMenuBar: |
DrawMenuBar(); |
menuResult = MenuSelect(theEvent->where); |
if (HiWord(menuResult) != 0) |
MenuDoChoice(menuResult); |
break; |
case inSysWindow: |
SystemClick(theEvent, whichWindow); |
break; |
} |
return (true); |
} |
//¥ ------------------------------ DefaultKeyDown |
static Boolean |
DefaultKeyDown(EventRecord *theEvent) |
{ |
SInt8 theKey; |
SInt8 theCode; |
SInt32 menuResult; |
theKey = theEvent->message & charCodeMask; |
theCode = (theEvent->message & keyCodeMask) >> 8; |
if ((theEvent->modifiers & cmdKey) != 0) |
{ |
menuResult = MenuKey(theKey); |
if (HiWord(menuResult) != 0) |
MenuDoChoice(menuResult); |
return (true); |
} |
if ('e' == theKey) |
GraphicsDoUpdateEvent(); |
return (true); |
} |
//¥ ------------------------------ DoDiskEvent |
static Boolean |
DoDiskEvent(EventRecord *theEvent) |
{ |
Point thePoint; |
SInt16 value; |
if (theEvent->message & 0xFFFF0000) //¥ Error mounting disk |
{ |
SetPt(&thePoint, 100, 100); |
value = DIBadMount(thePoint, theEvent->message); |
} |
return (true); |
} |
//¥ ------------------------------ RegisterEventHandlers |
void |
RegisterEventHandlers(EventHandlerProc keyDown, EventHandlerProc autoKey, EventHandlerProc mouseDown, |
EventHandlerProc update, EventHandlerProc idle) |
{ |
gEventHandlers.keyHandler = keyDown; |
gEventHandlers.autoKeyHandler = autoKey; |
gEventHandlers.clickHandler = mouseDown; |
gEventHandlers.updateHandler = update; |
gEventHandlers.idleHandler = idle; |
} |
//¥ ------------------------------ ModifyEventHandlers |
void |
ModifyEventHandlers(EventHandlerProc keyDown, EventHandlerProc autoKey, EventHandlerProc mouseDown, |
EventHandlerProc update, EventHandlerProc idle) |
{ |
if (keyDown) |
gEventHandlers.keyHandler = keyDown; |
if (autoKey) |
gEventHandlers.autoKeyHandler = autoKey; |
if (mouseDown) |
gEventHandlers.clickHandler = mouseDown; |
if (update) |
gEventHandlers.updateHandler = update; |
if (idle) |
gEventHandlers.idleHandler = idle; |
} |
//¥ -------------------- DoSuspend |
//¥ |
//¥ This is a small, local event loop. All it does is fetch screen update |
//¥ events and wait to get put back in the foreground. |
static void |
DoSuspend(void) |
{ |
EventRecord theEvent; |
while (true) |
{ |
//¥ Only check for resume and update events. While doing so, give TONS of time to other apps |
if (WaitNextEvent(osMask, &theEvent, 32767, nil)) |
{ |
if (theEvent.message & 0x01000000) //¥ Suspend/resume event |
{ |
if (theEvent.message & 0x00000001) //¥ Resume |
{ |
Boolean dummy; |
//¥ Make sure that DrawSprocket knows that we've resumed |
DSpProcessEvent(&theEvent, &dummy); |
} |
break; |
} |
} |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14