/* * $Logfile: /DescentIII/Main/ddio_mac/macController.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003/08/26 03:56:55 $ * $Author: kevinb $ * * Keyboard IO for macintosh * * $Log: macController.cpp,v $ * Revision 1.1.1.1 2003/08/26 03:56:55 kevinb * initial 1.5 import * * * 5 4/12/00 6:52p Matt * From Duane for 1.4: deadzone stuff * * 4 3/20/00 12:43p Matt * Merge of Duane's post-1.3 changes. * * 3 10/21/99 3:33p Jeff * Macintosh merges * * 2 7/28/99 3:31p Kevin * Mac Stuff! * * 4 5/21/97 5:17 PM Jeremy * switch keyboard controls to default values of PC (still need to * implement needs/controls structure) * * 3 5/15/97 1:43 AM Jeremy * changed mprintf's to be standard (with newline at end) * * 2 5/13/97 11:45 AM Jeremy * implementation for gameMacController object as well as create/destroy * controller object (still stubbed out) * * 1 5/11/97 8:09 PM Jeremy * Initial check in * * $NoKeywords: $ */ // ---------------------------------------------------------------------------- // Keyboard Interface // ---------------------------------------------------------------------------- // ANSI Headers #include #include // Macintosh Headers #include #include #include "InSprocket.h" // Descent 3 Headers #include "pserror.h" #include "mono.h" #include "macController.h" #include "Controller.h" #include "controls.h" #include "ddio_common.h" #include "ddio.h" #include "hud.h" #define SIGN(a) ((a < 0) ? -1 : 1) typedef struct { ubyte pcAction; ubyte isEvent; } PC_IS_Map; PC_IS_Map m_pc_is_map[] = {{ctfFORWARD_THRUSTAXIS, kInputEvent_None}, {ctfFORWARD_THRUSTKEY, kInputEvent_None}, {ctfREVERSE_THRUSTKEY, kInputEvent_None}, {ctfUP_THRUSTAXIS, kInputEvent_None}, {ctfUP_THRUSTKEY, kInputEvent_None}, {ctfDOWN_THRUSTKEY, kInputEvent_None}, {ctfRIGHT_THRUSTAXIS, kInputEvent_None}, {ctfRIGHT_THRUSTKEY, kInputEvent_None}, {ctfLEFT_THRUSTKEY, kInputEvent_None}, {ctfPITCH_DOWNAXIS, kInputEvent_None}, {ctfPITCH_DOWNKEY, kInputEvent_None}, {ctfPITCH_UPKEY, kInputEvent_None}, {ctfBANK_RIGHTAXIS, kInputEvent_None}, {ctfBANK_RIGHTKEY, kInputEvent_None}, {ctfBANK_LEFTKEY, kInputEvent_None}, {ctfHEADING_RIGHTAXIS, kInputEvent_None}, {ctfHEADING_RIGHTKEY, kInputEvent_None}, {ctfHEADING_LEFTKEY, kInputEvent_None}, {ctfFIREPRIMARY_BUTTON, kInputEvent_FirePrim_On}, {ctfFIREPRIMARY_KEY, kInputEvent_None}, {ctfFIREPRIMARY_KEY2, kInputEvent_None}, {ctfFIRESECONDARY_BUTTON, kInputEvent_FireSecond_On}, {ctfFIRESECONDARY_KEY, kInputEvent_None}, {ctfTOGGLE_SLIDEKEY, kInputEvent_None}, {ctfTOGGLE_SLIDEBUTTON, kInputEvent_Slide_On}, {ctfFIREFLARE_KEY, kInputEvent_None}, {ctfFIREFLARE_BUTTON, kInputEvent_Flare}, {ctfUP_BUTTON, kInputEvent_SlideUp_On}, {ctfDOWN_BUTTON, kInputEvent_SlideDown_On}, {ctfLEFT_BUTTON, kInputEvent_SlideLeft_On}, {ctfRIGHT_BUTTON, kInputEvent_SlideRight_On}, {ctfAFTERBURN_KEY, kInputEvent_None}, {ctfAFTERBURN_BUTTON, kInputEvent_AfterBurn_On}, {ctfFORWARD_BUTTON, kInputEvent_Accelerate_On}, {ctfREVERSE_BUTTON, kInputEvent_Reverse_On}, {ctfTOGGLE_BANKKEY, kInputEvent_None}, {ctfTOGGLE_BANKBUTTON, kInputEvent_Bank_On}, {ctfHEADING_LEFTBUTTON, kInputEvent_TurnLeft_On}, {ctfHEADING_RIGHTBUTTON, kInputEvent_TurnRight_On}, {ctfPITCH_UPBUTTON, kInputEvent_PitchUp_On}, {ctfPITCH_DOWNBUTTON, kInputEvent_PitchDown_On}, {ctfBANK_LEFTBUTTON, kInputEvent_BankLeft_On}, {ctfBANK_RIGHTBUTTON, kInputEvent_BankRight_On}, {ctfAUTOMAP_KEY, kInputEvent_None}, {ctfPREV_INVKEY, kInputEvent_None}, {ctfNEXT_INVKEY, kInputEvent_None}, {ctfINV_USEKEY, kInputEvent_None}, {ctfPREV_CNTMSKEY, kInputEvent_None}, {ctfNEXT_CNTMSKEY, kInputEvent_None}, {ctfCNTMS_USEKEY, kInputEvent_None}, {ctfHEADLIGHT_KEY, kInputEvent_None}, {ctfHEADLIGHT_BUTTON, kInputEvent_HeadLight}, {ctfAUTOMAP_BUTTON, kInputEvent_Map}, {ctfPREV_INVBTN, kInputEvent_InventoryPrev}, {ctfNEXT_INVBTN, kInputEvent_InventoryNext}, {ctfINV_USEBTN, kInputEvent_InventoryUse}, {ctfPREV_CNTMSBTN, kInputEvent_CounterPrev}, {ctfNEXT_CNTMSBTN, kInputEvent_CounterNext}, {ctfCNTMS_USEBTN, kInputEvent_CounterUse}, {ctfWPNSEL_PCYCLEKEY, kInputEvent_None}, {ctfWPNSEL_PCYCLEBTN, kInputEvent_NextPrim}, {ctfWPNSEL_SCYCLEKEY, kInputEvent_None}, {ctfWPNSEL_SCYCLEBTN, kInputEvent_NextSecond}, {ctfREARVIEW_KEY, kInputEvent_None}, {ctfREARVIEW_BTN, kInputEvent_RearView_On}, {ctfAUDIOTAUNT1_KEY, kInputEvent_None}, {ctfAUDIOTAUNT1_BTN, kInputEvent_ATaunt1}, {ctfAUDIOTAUNT2_KEY, kInputEvent_None}, {ctfAUDIOTAUNT2_BTN, kInputEvent_ATaunt2}, {ctfAUDIOTAUNT3_KEY, kInputEvent_None}, {ctfAUDIOTAUNT3_BTN, kInputEvent_ATaunt3}, {ctfAUDIOTAUNT4_KEY, kInputEvent_None}, {ctfAUDIOTAUNT4_BTN, kInputEvent_ATaunt4}}; inline ubyte ConvertPC_IS(ubyte action) { if (m_pc_is_map[action].pcAction == action) { return m_pc_is_map[action].isEvent; } else { for (int i = 0; i < NUM_CONTROLLER_FUNCTIONS; i++) { if (m_pc_is_map[i].pcAction == action) { return m_pc_is_map[i].isEvent; } } } return 0; } struct { float DownTime; float UpTime; bool state; } iSbutton[kNumEvents]; gameMacController::gameMacController(int num_funcs, ct_function *gameFunctions, char *remote_adr) : gameController(num_funcs, gameFunctions) { for (int i = 0; i < kNumEvents; i++) { iSbutton[i].DownTime = 0.0; iSbutton[i].UpTime = 0.0; iSbutton[i].state = false; } // inSprocket_Init(); enum_controllers(remote_adr); for (int i = 0; i < num_funcs; i++) assign_function(&gameFunctions[i]); m_Suspended = 0; // m_frame_timer_ms = -1; // m_frame_time = 1.0f; // m_ControlList[MC_JOY].deadzone = 8; gameMacController::flush(); } gameMacController::~gameMacController(void) { // inSprocket_Exit(); } // these functions suspend or resume any controller reading. this is really only useful for // preemptive controller polling, but they should be used to activate and deactivate controller // reading. void gameMacController::suspend() { inSprocket_Activate(false); for (int i = 0; i < kNumEvents; i++) { iSbutton[i].DownTime = 0.0; iSbutton[i].UpTime = 0.0; iSbutton[i].state = false; } } void gameMacController::flush() { InSprocket_Flush(); for (int i = 0; i < kNumEvents; i++) { iSbutton[i].DownTime = 0; iSbutton[i].UpTime = 0; iSbutton[i].state = false; } } void gameMacController::resume() { inSprocket_Activate(true); } // this functions polls the controllers if needed. some systems may not need to implement // this function. #define IS_MOUSE 0 #define IS_JOY 1 float is_mouse[6]; int is_joy[6]; void MacInSprocketHandler(void) { TInputEvent iSevent; float cur_time = timer_GetTime(); is_mouse[kNeed_Yaw] = inSprocket_GetMouse(kNeed_Yaw); is_mouse[kNeed_Pitch] = inSprocket_GetMouse(kNeed_Pitch); is_mouse[kNeed_Roll] = inSprocket_GetMouse(kNeed_Roll); is_mouse[kNeed_MoveX] = inSprocket_GetMouse(kNeed_MoveX); is_mouse[kNeed_MoveZ] = inSprocket_GetMouse(kNeed_MoveZ); is_mouse[kNeed_MoveY] = inSprocket_GetMouse(kNeed_MoveY); is_joy[kNeed_Yaw] = inSprocket_GetAxisInt(kNeed_Yaw); is_joy[kNeed_Pitch] = inSprocket_GetAxisInt(kNeed_Pitch); is_joy[kNeed_Roll] = inSprocket_GetAxisInt(kNeed_Roll); is_joy[kNeed_MoveX] = inSprocket_GetAxisInt(kNeed_MoveX); is_joy[kNeed_MoveZ] = inSprocket_GetAxisInt(kNeed_MoveZ); is_joy[kNeed_MoveY] = inSprocket_GetAxisInt(kNeed_MoveY); while ((iSevent = inSprocket_GetButtonEvent()) != kInputEvent_None) { switch (iSevent) { case kInputEvent_Accelerate_On: case kInputEvent_Reverse_On: case kInputEvent_SlideLeft_On: case kInputEvent_SlideRight_On: case kInputEvent_SlideUp_On: case kInputEvent_SlideDown_On: case kInputEvent_BankLeft_On: case kInputEvent_BankRight_On: case kInputEvent_TurnLeft_On: case kInputEvent_TurnRight_On: case kInputEvent_PitchUp_On: case kInputEvent_PitchDown_On: case kInputEvent_FirePrim_On: case kInputEvent_FireSecond_On: iSbutton[iSevent].state = true; if (iSbutton[iSevent].DownTime == 0.0) iSbutton[iSevent].DownTime = cur_time; break; case kInputEvent_Accelerate_Off: case kInputEvent_Reverse_Off: case kInputEvent_SlideLeft_Off: case kInputEvent_SlideRight_Off: case kInputEvent_SlideUp_Off: case kInputEvent_SlideDown_Off: case kInputEvent_BankLeft_Off: case kInputEvent_BankRight_Off: case kInputEvent_TurnLeft_Off: case kInputEvent_TurnRight_Off: case kInputEvent_PitchUp_Off: case kInputEvent_PitchDown_Off: case kInputEvent_FirePrim_Off: case kInputEvent_FireSecond_Off: iSbutton[iSevent - 1].state = false; iSbutton[iSevent - 1].UpTime = cur_time; break; case kInputEvent_CounterUse: case kInputEvent_CounterNext: case kInputEvent_CounterPrev: case kInputEvent_InventoryUse: case kInputEvent_InventoryNext: case kInputEvent_InventoryPrev: case kInputEvent_NextPrim: case kInputEvent_NextSecond: case kInputEvent_Map: case kInputEvent_Flare: case kInputEvent_HeadLight: case kInputEvent_Bank_On: case kInputEvent_Slide_On: case kInputEvent_AfterBurn_On: case kInputEvent_RearView_On: iSbutton[iSevent].state = true; break; case kInputEvent_Bank_Off: case kInputEvent_Slide_Off: case kInputEvent_AfterBurn_Off: case kInputEvent_RearView_Off: iSbutton[iSevent - 1].state = false; break; } } } void gameMacController::poll() { // TInputEvent iSevent; // extern float Frametime; /* float cur_time = timer_GetTime(); // while((iSevent = inSprocket_GetEvent()) != kInputEvent_None) { for(int i = 0; i < kNumEvents; i++) { switch(i) { case kInputEvent_SlideLeft_On: mprintf((1, "ln %f %f\n", iSbutton[i].UpTime, iSbutton[i].DownTime)); break; } switch(i) { case kInputEvent_EnergyShield_Off: case kInputEvent_Accelerate_Off: case kInputEvent_Reverse_Off: case kInputEvent_SlideLeft_Off: case kInputEvent_SlideRight_Off: case kInputEvent_SlideUp_Off: case kInputEvent_SlideDown_Off: case kInputEvent_BankLeft_Off: case kInputEvent_BankRight_Off: case kInputEvent_TurnLeft_Off: case kInputEvent_TurnRight_Off: case kInputEvent_PitchUp_Off: case kInputEvent_PitchDown_Off: iSbutton[i-1].UpTime = cur_time; break; case kInputEvent_Flare: case kInputEvent_Bomb: case kInputEvent_Map: case kInputEvent_NextPrim: case kInputEvent_PrevPrim: case kInputEvent_NextSecond: case kInputEvent_PrevSecond: case kInputEvent_HeadLight: case kInputEvent_Bank_On: case kInputEvent_Slide_On: case kInputEvent_FirePrim_On: case kInputEvent_FireSecond_On: case kInputEvent_AfterBurn_On: case kInputEvent_RearView_On: case kInputEvent_CounterPrev: if(iSbutton[i].DownTime != 0.0) iSbutton[i].DeltaTime = 1.0; if(iSbutton[i].UpTime) { iSbutton[i].DownTime = iSbutton[i].UpTime = 0.0; } break; case kInputEvent_Accelerate_On: case kInputEvent_Reverse_On: case kInputEvent_SlideLeft_On: case kInputEvent_BankRight_On: case kInputEvent_TurnRight_On: case kInputEvent_SlideDown_On: case kInputEvent_PitchUp_On: case kInputEvent_SlideRight_On: case kInputEvent_BankLeft_On: case kInputEvent_TurnLeft_On: case kInputEvent_SlideUp_On: case kInputEvent_PitchDown_On: if(iSbutton[i].DownTime != 0.0) { iSbutton[i].DeltaTime = cur_time - iSbutton[i].DownTime; } break; case kInputEvent_Bank_Off: case kInputEvent_Slide_Off: case kInputEvent_FirePrim_Off: case kInputEvent_FireSecond_Off: case kInputEvent_AfterBurn_Off: case kInputEvent_RearView_Off: case kInputEvent_InventoryPrev: case kInputEvent_CounterNext: case kInputEvent_EnergyShield_Off: case kInputEvent_Accelerate_Off: case kInputEvent_Reverse_Off: case kInputEvent_SlideLeft_Off: case kInputEvent_SlideRight_Off: case kInputEvent_SlideUp_Off: case kInputEvent_SlideDown_Off: case kInputEvent_BankLeft_Off: case kInputEvent_BankRight_Off: case kInputEvent_TurnLeft_Off: case kInputEvent_TurnRight_Off: case kInputEvent_PitchUp_Off: case kInputEvent_PitchDown_Off: if(iSbutton[i-1].DownTime != 0.0) { if(iSbutton[i-1].UpTime != 0) iSbutton[i-1].DeltaTime = iSbutton[i-1].UpTime - iSbutton[i-1].DownTime; iSbutton[i-1].UpTime = iSbutton[i-1].DownTime = 0.0; } else { iSbutton[i-1].DeltaTime = 0.0; } break; } } */ } // all systems need to implement this function. this returns information about the controller bool gameMacController::get_packet(int id, ct_packet *packet, ct_format alt_format) { bool success = false; float val = (float)0.0; packet->flags = 0; int i; packet->format = (alt_format != ctNoFormat) ? alt_format : m_ElementList[id].format; alt_format = packet->format; if (!m_ElementList[id].enabled) { return success; } if (m_ElementList[id].ctype[0] == ctKey) val += get_key_value(m_ElementList[id].value[0], alt_format); if (m_ElementList[id].ctype[1] == ctKey) val += get_key_value(m_ElementList[id].value[1], alt_format); if (m_ElementList[id].ctype[0] == ctButton) val += get_button_value(id); if (m_ElementList[id].ctype[1] == ctButton) val += get_button_value(id); if (m_ElementList[id].ctype[0] == ctAxis) val += get_axis_value(0, m_ElementList[id].value[0], alt_format, false); if (val) packet->flags |= CTPK_ELEMENTACTIVE; packet->value = val; return success; } gameController *CreateController(int num_funcs, ct_function *gameFunctions, char *remote_ip) { mprintf((0, "Creating mac game controller.\n")); return new gameMacController(num_funcs, gameFunctions); } void DestroyController(gameController *ctl) { mprintf((0, "Destroying mac game controller.\n")); if (ctl) delete ctl; } // temporarily enables or disables a function void gameMacController::enable_function(int id, bool enable) { m_ElementList[id].enabled = enable; } // returns information about a requested function void gameMacController::get_controller_function(int id, ct_type *type, ct_config_data *value, ubyte *flags) { type[0] = m_ElementList[id].ctype[0]; type[1] = m_ElementList[id].ctype[1]; *value = makeword(CONTROLLER_CTL_INFO(m_ElementList[id].ctl[0], m_ElementList[id].ctl[1]), CONTROLLER_CTL_VALUE(m_ElementList[id].value[0], m_ElementList[id].value[1])); flags[0] = m_ElementList[id].flags[0]; flags[1] = m_ElementList[id].flags[1]; } // sets the configuration of a function void gameMacController::set_controller_function(int id, const ct_type *type, ct_config_data value, const ubyte *flags) { ct_element elem; if (id >= CT_MAX_ELEMENTS) return; // auto assign keyboard controller if type is key. if (type[0] == ctKey) elem.ctl[0] = CONTROLLER_CTL1_INFO(0); else elem.ctl[0] = CONTROLLER_CTL1_INFO(CONTROLLER_INFO(value)); if (type[1] == ctKey) elem.ctl[1] = CONTROLLER_CTL2_INFO(0); else elem.ctl[1] = CONTROLLER_CTL2_INFO(CONTROLLER_INFO(value)); elem.ctype[0] = type[0]; elem.ctype[1] = type[1]; elem.format = m_ElementList[id].format; elem.value[0] = CONTROLLER_CTL1_VALUE(CONTROLLER_VALUE(value)); elem.value[1] = CONTROLLER_CTL2_VALUE(CONTROLLER_VALUE(value)); elem.flags[0] = flags[0]; elem.flags[1] = flags[1]; elem.enabled = m_ElementList[id].enabled; // if controller doesn't exist, set it to invalid. if (elem.ctl[0] > CT_MAX_CONTROLLERS) elem.ctl[0] = NULL_WINCONTROLLER; if (elem.ctl[1] >= CT_MAX_CONTROLLERS) elem.ctl[1] = NULL_WINCONTROLLER; assign_element(id, &elem); } #define TABLE_LOOKUP // note controller is index into ControlList. float gameMacController::get_axis_value(sbyte controller, ubyte axis, ct_format format, bool invert) { float axisval = 0.0; switch (axis) { // note we take care of mouse controls and external controls here case CT_X_AXIS: axisval += is_mouse[kNeed_Yaw]; if (ABS(is_joy[kNeed_Yaw]) > m_ControlList[MC_JOY].deadzone && m_ControlList[MC_JOY].sens[AXIS_YAW] != 0.0) { #if defined TABLE_LOOKUP axisval += SIGN(is_joy[kNeed_Yaw]) * m_ControlList[MC_JOY].sens_curve[AXIS_YAW][ABS(is_joy[kNeed_Yaw])]; #elif defined REAL_POW if (m_ControlList[MC_JOY].sens[AXIS_YAW] == 1.0) axisval += is_joy[kNeed_Yaw]; else axisval += powf(ABS(is_joy[kNeed_Yaw]), m_ControlList[MC_JOY].inv_sens[AXIS_YAW]) * SIGN(is_joy[kNeed_Yaw]); #else axisval += is_joy[kNeed_Yaw] * m_ControlList[MC_JOY].sens[AXIS_YAW]; #endif } break; case CT_Y_AXIS: axisval -= is_mouse[kNeed_Pitch]; if (ABS(is_joy[kNeed_Pitch]) > m_ControlList[MC_JOY].deadzone && m_ControlList[MC_JOY].sens[AXIS_PITCH] != 0.0) { #if defined TABLE_LOOKUP axisval -= SIGN(is_joy[kNeed_Pitch]) * m_ControlList[MC_JOY].sens_curve[AXIS_PITCH][ABS((int)(is_joy[kNeed_Pitch]))]; #elif defined REAL_POW if (m_ControlList[MC_JOY].sens[AXIS_PITCH] == 1.0) axisval -= is_joy[kNeed_Pitch]; else axisval -= powf(ABS(is_joy[kNeed_Pitch]), m_ControlList[MC_JOY].inv_sens[AXIS_PITCH]) * SIGN(is_joy[kNeed_Pitch]); #else axisval -= is_joy[kNeed_Pitch] * m_ControlList[MC_JOY].sens[AXIS_PITCH]; #endif } break; case CT_R_AXIS: axisval += is_mouse[kNeed_Roll]; if (ABS(is_joy[kNeed_Roll]) > m_ControlList[MC_JOY].deadzone && m_ControlList[MC_JOY].sens[AXIS_ROLL] != 0.0) { #if defined TABLE_LOOKUP axisval += SIGN(is_joy[kNeed_Roll]) * m_ControlList[MC_JOY].sens_curve[AXIS_ROLL][ABS((int)(is_joy[kNeed_Roll]))]; #elif defined REAL_POW if (m_ControlList[MC_JOY].sens[AXIS_ROLL] == 1.0) axisval += is_joy[kNeed_Roll]; else axisval += powf(ABS(is_joy[kNeed_Roll]), m_ControlList[MC_JOY].inv_sens[AXIS_ROLL]) * SIGN(is_joy[kNeed_Roll]); #else axisval += is_joy[kNeed_Roll] * m_ControlList[MC_JOY].sens[AXIS_ROLL]; #endif } break; case CT_Z_AXIS: axisval -= is_mouse[kNeed_MoveZ]; if (ABS(is_joy[kNeed_MoveZ]) > m_ControlList[MC_JOY].deadzone && m_ControlList[MC_JOY].sens[AXIS_FORWARD] != 0.0) { #if defined TABLE_LOOKUP axisval -= SIGN(is_joy[kNeed_MoveZ]) * m_ControlList[MC_JOY].sens_curve[AXIS_FORWARD][ABS((int)(is_joy[kNeed_MoveZ]))]; #elif defined REAL_POW if (m_ControlList[MC_JOY].sens[AXIS_FORWARD] == 1.0) axisval -= is_joy[kNeed_MoveZ]; else axisval -= powf(ABS(is_joy[kNeed_MoveZ]), m_ControlList[MC_JOY].inv_sens[AXIS_FORWARD]) * SIGN(is_joy[kNeed_MoveZ]); #else axisval -= is_joy[kNeed_MoveZ] * m_ControlList[MC_JOY].sens[AXIS_FORWARD]; #endif } break; case CT_U_AXIS: axisval += is_mouse[kNeed_MoveX]; if (ABS(is_joy[kNeed_MoveX]) > m_ControlList[MC_JOY].deadzone && m_ControlList[MC_JOY].sens[AXIS_SIDE] != 0.0) { #if defined TABLE_LOOKUP axisval += SIGN(is_joy[kNeed_MoveX]) * m_ControlList[MC_JOY].sens_curve[AXIS_SIDE][ABS((int)(is_joy[kNeed_MoveX]))]; #elif defined REAL_POW if (m_ControlList[MC_JOY].sens[AXIS_SIDE] == 1.0) axisval += is_joy[kNeed_MoveX]; else axisval += powf(ABS(is_joy[kNeed_MoveX]), m_ControlList[MC_JOY].inv_sens[AXIS_SIDE]) * SIGN(is_joy[kNeed_MoveX]); #else axisval += is_joy[kNeed_MoveX] * m_ControlList[MC_JOY].sens[AXIS_SIDE]; #endif } break; case CT_V_AXIS: axisval -= is_mouse[kNeed_MoveY]; if (ABS(is_joy[kNeed_MoveY]) > m_ControlList[MC_JOY].deadzone && m_ControlList[MC_JOY].sens[AXIS_VERT] != 0.0) { #if defined TABLE_LOOKUP axisval -= SIGN(is_joy[kNeed_MoveY]) * m_ControlList[MC_JOY].sens_curve[AXIS_VERT][ABS((int)(is_joy[kNeed_MoveY]))]; #elif defined REAL_POW if (m_ControlList[MC_JOY].sens[AXIS_VERT] == 1.0) axisval -= is_joy[kNeed_MoveY]; else axisval -= powf(ABS(is_joy[kNeed_MoveY]), m_ControlList[MC_JOY].inv_sens[AXIS_VERT]) * SIGN(is_joy[kNeed_MoveY]); #else axisval -= is_joy[kNeed_MoveY] * m_ControlList[MC_JOY].sens[AXIS_VERT]; #endif } break; default: mprintf((2, "invalid axis %d\n", axis)); Int3(); // NOT A VALID AXIS break; } // mprintf((2, "x %d y %d z %d p %d h %d r %d\n", //is_joy[kNeed_MoveX],is_joy[kNeed_MoveY],is_joy[kNeed_MoveZ],is_joy[kNeed_Pitch],is_joy[kNeed_Yaw],is_joy[kNeed_Roll])); return axisval; } // get keyboard info float gameMacController::get_key_value(int key, ct_format format) { float val = (float)0.0; ASSERT(key < DDIO_MAX_KEYS); switch (format) { // note we take care of mouse controls and external controls here case ctDigital: if (KEY_STATE(key)) val = 1.0f; break; case ctDownCount: val = (float)ddio_KeyDownCount(key); break; case ctTime: val = (float)ddio_KeyDownTime(key); break; default: mprintf((1, "gameController::key unsupported format for function\n")); } return val; } // get keyboard info float gameMacController::get_button_value(int button) { float down_time = (float)0.0; int sprockButton = ConvertPC_IS(button); float cur_time = timer_GetTime(); switch (button) { case ctfAFTERBURN_BUTTON: case ctfTOGGLE_SLIDEBUTTON: case ctfTOGGLE_BANKBUTTON: if (iSbutton[sprockButton].state) down_time = 1; else down_time = 0; break; case ctfWPNSEL_PCYCLEBTN: case ctfWPNSEL_SCYCLEBTN: case ctfREARVIEW_BTN: case ctfPREV_CNTMSBTN: case ctfNEXT_CNTMSBTN: case ctfCNTMS_USEBTN: case ctfPREV_INVBTN: case ctfNEXT_INVBTN: case ctfINV_USEBTN: case ctfHEADLIGHT_BUTTON: case ctfFIREFLARE_BUTTON: case ctfAUTOMAP_BUTTON: if (iSbutton[sprockButton].state) { down_time = 1; iSbutton[sprockButton].state = false; } else { down_time = 0; } break; default: if (iSbutton[sprockButton].state) { if (iSbutton[sprockButton].DownTime != 0.0) { down_time = cur_time - iSbutton[sprockButton].DownTime; } } else { if (iSbutton[sprockButton].UpTime != 0.0 && iSbutton[sprockButton].DownTime != 0.0) { down_time = iSbutton[sprockButton].UpTime - iSbutton[sprockButton].DownTime; iSbutton[sprockButton].UpTime = iSbutton[sprockButton].DownTime = 0.0; } } } if (!(button == ctfFIREPRIMARY_BUTTON || button == ctfFIRESECONDARY_BUTTON)) if (down_time > 1.0) down_time = 1.0; return down_time; } int gameMacController::assign_function(ct_function *func) { // for now this is a straight forward translation (that is, no mapping of needs to controller // list to create elements. ct_element elem; int i; for (i = 0; i < CTLBINDS_PER_FUNC; i++) { elem.ctl[i] = NULL_WINCONTROLLER; switch (func->ctype[i]) { case ctNone: break; case ctKey: elem.ctl[i] = 0; break; case ctAxis: elem.ctl[i] = get_axis_controller(func->value[i]); break; case ctButton: elem.ctl[i] = get_button_controller(func->value[i]); break; case ctMouseAxis: elem.ctl[i] = 1; break; case ctMouseButton: // find a free mouse button. if ((m_ControlList[1].btnmask & (1 << (func->value[i] - 1))) && ((func->value[i] - 1) < m_ControlList[1].buttons)) { elem.ctl[i] = 1; } break; case ctPOV: elem.ctl[i] = get_pov_controller(); break; } elem.ctype[i] = func->ctype[i]; elem.value[i] = func->value[i]; } elem.format = func->format; elem.flags[0] = func->flags[0]; elem.flags[1] = func->flags[1]; elem.enabled = true; assign_element(func->id, &elem); return func->id; } // sets up an elements information structure void gameMacController::assign_element(int id, ct_element *elem) { // assign element, check to see if valid. int i; m_ElementList[id].format = elem->format; m_ElementList[id].flags[0] = elem->flags[0]; m_ElementList[id].flags[1] = elem->flags[1]; m_ElementList[id].enabled = elem->enabled; // look through each controller and validate each element for (i = 0; i < CTLBINDS_PER_FUNC; i++) { m_ElementList[id].ctl[i] = elem->ctl[i]; m_ElementList[id].value[i] = elem->value[i]; m_ElementList[id].ctype[i] = elem->ctype[i]; if (m_ElementList[id].ctl[i] != NULL_WINCONTROLLER) { // this function shouldn't do any error checking!!!! keep same controller values and bindings unless // bindings are truly bogus. switch (m_ElementList[id].ctype[i]) { case ctMouseButton: case ctButton: if (elem->value[i] > CT_MAX_BUTTONS) { m_ElementList[id].ctl[i] = NULL_WINCONTROLLER; m_ElementList[id].value[i] = NULL_BINDING; } break; case ctMouseAxis: case ctAxis: // if (!(m_ControlList[elem->ctl[i]].flags & (1<<(elem->value[i]-1)))) // m_ElementList[id].ctl[i] = NULL_WINCONTROLLER; break; case ctPOV: // if (!(m_ControlList[elem->ctl[i]].flags & CTF_POV)) // m_ElementList[id].ctl[i] = NULL_WINCONTROLLER; break; case ctKey: break; default: m_ElementList[id].value[i] = NULL_BINDING; m_ElementList[id].ctl[i] = NULL_WINCONTROLLER; } } else { m_ElementList[id].value[i] = NULL_BINDING; } } } sbyte gameMacController::get_axis_controller(ubyte axis) { return 2; // return NULL_CONTROLLER; } sbyte gameMacController::get_button_controller(ubyte btn) { return NULL_CONTROLLER; } sbyte gameMacController::get_pov_controller() { return NULL_CONTROLLER; } // enumerate all controllers on system bool gameMacController::enum_controllers(char *remote_adr) { int num_devs = 0, dev; int i; for (i = 0; i < CT_MAX_CONTROLLERS; i++) m_ControlList[i].id = CTID_INVALID; // Add keyboard controller m_ControlList[num_devs].id = CTID_KEYBOARD; m_ControlList[num_devs].buttons = 0; m_ControlList[num_devs].flags = 0; num_devs++; return true; } // gets sensitivity of axis item float gameMacController::get_axis_sensitivity(ct_type axis_type, ubyte axis) { axis--; ASSERT(axis < CT_NUM_AXES); switch (axis_type) { case ctMouseAxis: return m_ControlList[1].sens[axis]; case ctAxis: return m_ControlList[MC_JOY].sens[axis]; default: Int3(); } return 0.0f; } // sets sensitivity of axis item void gameMacController::set_axis_sensitivity(ct_type axis_type, ubyte axis, float val) { int i; axis--; ASSERT(axis < CT_NUM_AXES); switch (axis_type) { case ctMouseAxis: m_ControlList[1].sens[axis] = val; break; case ctAxis: for (i = 2; i < CT_MAX_CONTROLLERS; i++) { m_ControlList[i].sens[axis] = val; // m_ControlList[i].inv_sens[axis] = 1.0/val; m_ControlList[i].sens_curve[axis][0] = 0; for (int j = 1; j <= JOY_SAMPLES; j++) { m_ControlList[i].sens_curve[axis][j] = powf((float)j / (float)(JOY_SAMPLES), 1.0 / val); } } break; default: Int3(); } } //#ifndef MACINTOSH // toggles use of deadzone for controllers. ctl can be 0 to ??? // dead zone is from 0.0 to 0.5 void gameMacController::set_controller_deadzone(int ctl, float deadzone) { if (deadzone < 0.0) deadzone = 0.0; if (deadzone > 25) deadzone = 25; m_ControlList[MC_JOY].deadzone = deadzone * 2; } float gameMacController::get_controller_deadzone(int ctl) { float val = m_ControlList[MC_JOY].deadzone / 2; return val; } //#endif char Ctltext_AxisBindings[][16] = {"", "X-axis", "Y-axis", "Z-axis", "R-axis", "U-axis", "V-axis"}; char Ctltext_BtnBindings[][16] = {"", "btn1", "btn2", "btn3", "btn4", "btn5", "btn6", "btn7", "btn8", "btn9", "btn10", "btn11", "btn12", "btn13", "btn14", "btn15", "btn16", "btn17", "btn18", "btn19", "btn20", "btn21", "btn22", "btn23", "btn24", "btn25", "btn26", "btn27", "btn28", "btn29", "btn30", "btn31", "btn32"}; char Ctltext_PovBindings[][16] = {"", "pov-U", "pov-R", "pov-D", "pov-L"}; #define NUM_AXISBINDSTRINGS (sizeof(Ctltext_AxisBindings) / sizeof(Ctltext_AxisBindings[0])) #define NUM_BTNBINDSTRINGS (sizeof(Ctltext_BtnBindings) / sizeof(Ctltext_AxisBindings[0])) #ifdef MACINTOSH // retrieves binding text for desired function, binding, etc. const char *gameMacController::get_binding_text(ct_type type, ubyte ctrl, ubyte bind) { static char binding_text[16]; const char *str; if (ctrl == NULL_CONTROLLER) { return NULL; } switch (type) { case ctAxis: { ASSERT(bind < NUM_AXISBINDSTRINGS); str = Ctltext_AxisBindings[bind]; if ((ctrl - 2) > 0) { sprintf(binding_text, "J%d:%s", (ctrl - 2) + 1, str); } else { return str; } break; } case ctMouseAxis: { str = ddio_MouseGetAxisText(((sbyte)bind) - 1); return str; } case ctButton: { ASSERT(bind < NUM_BTNBINDSTRINGS); str = Ctltext_BtnBindings[bind]; if ((ctrl - 2) > 0) { sprintf(binding_text, "J%d:%s", (ctrl - 2) + 1, str); } else { return str; } break; } case ctMouseButton: { str = ddio_MouseGetBtnText(((sbyte)bind) - 1); return str; } case ctPOV: case ctPOV2: case ctPOV3: case ctPOV4: { ushort povpos = bind; if (povpos == JOYPOV_UP) str = Ctltext_PovBindings[1]; else if (povpos == JOYPOV_DOWN) str = Ctltext_PovBindings[3]; else if (povpos == JOYPOV_LEFT) str = Ctltext_PovBindings[4]; else if (povpos == JOYPOV_RIGHT) str = Ctltext_PovBindings[2]; else str = Ctltext_PovBindings[0]; if ((ctrl - 2) > 0) { if (type - ctPOV) { sprintf(binding_text, "J%d:%s%d", (ctrl - 2) + 1, str, type - ctPOV); } else { sprintf(binding_text, "J%d:%s", (ctrl - 2) + 1, str); } } else { if (type - ctPOV) { sprintf(binding_text, "%s%d", str, type - ctPOV); } else { return str; } } break; } case ctKey: break; default: if (type == ctNone) { Int3(); } binding_text[0] = 0; } return binding_text; } #endif