Files
Descent3/ddio_mac/macController.cpp
Kevin Bentley df209742fc Initial import
2024-04-15 21:43:29 -06:00

975 lines
29 KiB
C++

/*
* $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 <stdlib.h>
#include <math.h>
// Macintosh Headers
#include <Events.h>
#include <InputSprocket.h>
#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