/*************************************************************************** file : controlconfig.cpp created : Wed Mar 12 21:20:34 CET 2003 copyright : (C) 2003 by Eric Espié email : eric.espie@torcs.org version : $Id: controlconfig.cpp,v 1.5 2003/11/23 20:21:11 torcs Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** @file @author Eric Espie @version $Id: controlconfig.cpp,v 1.5 2003/11/23 20:21:11 torcs Exp $ */ #include #include #include #include #include #include #include #include #include "controlconfig.h" #include "mouseconfig.h" #include "joystickconfig.h" static void *scrHandle = NULL; static void *prevHandle = NULL; static void *PrefHdle = NULL; static int MouseCalButton; static int JoyCalButton; static tCtrlMouseInfo mouseInfo; static char CurrentSection[256]; static tCmdInfo Cmd[] = { {HM_ATT_GEAR_R, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_GEAR_N, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_UP_SHFT, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_DN_SHFT, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_LIGHT1_CMD, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_ASR_CMD, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_LEFTSTEER, {1, GFCTRL_TYPE_MOUSE_AXIS}, 0, HM_ATT_LEFTSTEER_MIN, 0, HM_ATT_LEFTSTEER_MAX, 0, HM_ATT_LEFTSTEER_POW, 1.0, 1}, {HM_ATT_RIGHTSTEER, {2, GFCTRL_TYPE_MOUSE_AXIS}, 0, HM_ATT_RIGHTSTEER_MIN, 0, HM_ATT_RIGHTSTEER_MAX, 0, HM_ATT_RIGHTSTEER_POW, 1.0, 1}, {HM_ATT_THROTTLE, {1, GFCTRL_TYPE_MOUSE_BUT}, 0, HM_ATT_THROTTLE_MIN, 0, HM_ATT_THROTTLE_MAX, 0, HM_ATT_THROTTLE_POW, 1.0, 1}, {HM_ATT_BRAKE, {2, GFCTRL_TYPE_MOUSE_BUT}, 0, HM_ATT_BRAKE_MIN, 0, HM_ATT_BRAKE_MAX, 0, HM_ATT_BRAKE_POW, 1.0, 1}, {HM_ATT_CLUTCH, {3, GFCTRL_TYPE_MOUSE_BUT}, 0, HM_ATT_CLUTCH_MIN, 0, HM_ATT_CLUTCH_MAX, 0, HM_ATT_CLUTCH_POW, 1.0, 1}, {HM_ATT_ABS_CMD, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1}, {HM_ATT_SPDLIM_CMD, {-1, GFCTRL_TYPE_NOT_AFFECTED}, 0, 0, 0, 0, 0, 0, 0, 1} }; static int maxCmd = sizeof(Cmd) / sizeof(Cmd[0]); static jsJoystick *js[NUM_JOY] = {NULL}; static float ax[MAX_AXES * NUM_JOY] = {0}; static float axCenter[MAX_AXES * NUM_JOY]; static int rawb[NUM_JOY] = {0}; static float SteerSensVal; static float DeadZoneVal; static char buf[1024]; static int SteerSensEditId; static int DeadZoneEditId; static int ReloadValues = 1; static void onSteerSensChange(void * /* dummy */) { char *val; float fv; val = GfuiEditboxGetString(scrHandle, SteerSensEditId); if (sscanf(val, "%f", &fv) == 1) { sprintf(buf, "%f", fv); SteerSensVal = fv; GfuiEditboxSetString(scrHandle, SteerSensEditId, buf); } else { GfuiEditboxSetString(scrHandle, SteerSensEditId, ""); } } static void onDeadZoneChange(void * /* dummy */) { char *val; float fv; val = GfuiEditboxGetString(scrHandle, DeadZoneEditId); if (sscanf(val, "%f", &fv) == 1) { sprintf(buf, "%f", fv); DeadZoneVal = fv; GfuiEditboxSetString(scrHandle, DeadZoneEditId, buf); } else { GfuiEditboxSetString(scrHandle, SteerSensEditId, ""); } } static void onSave(void * /* dummy */) { int i; char *str; GfParmSetNum(PrefHdle, CurrentSection, HM_ATT_STEER_SENS, NULL, SteerSensVal); GfParmSetNum(PrefHdle, CurrentSection, HM_ATT_STEER_DEAD, NULL, DeadZoneVal); for (i = 0; i < maxCmd; i++) { str = GfctrlGetNameByRef(Cmd[i].ref.type, Cmd[i].ref.index); if (str) { GfParmSetStr(PrefHdle, CurrentSection, Cmd[i].name, str); } else { GfParmSetStr(PrefHdle, CurrentSection, Cmd[i].name, ""); } if (Cmd[i].minName) { GfParmSetNum(PrefHdle, CurrentSection, Cmd[i].minName, NULL, Cmd[i].min); } if (Cmd[i].maxName) { GfParmSetNum(PrefHdle, CurrentSection, Cmd[i].maxName, NULL, Cmd[i].max); } if (Cmd[i].powName) { GfParmSetNum(PrefHdle, CurrentSection, Cmd[i].powName, NULL, Cmd[i].pow); } } GfParmWriteFile(NULL, PrefHdle, "preferences"); GfuiScreenActivate(prevHandle); } static void updateButtonText(void) { int i; char *str; int displayMouseCal = GFUI_INVISIBLE; int displayJoyCal = GFUI_INVISIBLE; for (i = 0; i < maxCmd; i++) { str = GfctrlGetNameByRef(Cmd[i].ref.type, Cmd[i].ref.index); if (str) { GfuiButtonSetText (scrHandle, Cmd[i].Id, str); } else { GfuiButtonSetText (scrHandle, Cmd[i].Id, "---"); } if (Cmd[i].ref.type == GFCTRL_TYPE_MOUSE_AXIS) { displayMouseCal = GFUI_VISIBLE; } else if (Cmd[i].ref.type == GFCTRL_TYPE_JOY_AXIS) { displayJoyCal = GFUI_VISIBLE; } } sprintf(buf, "%f", SteerSensVal); GfuiEditboxSetString(scrHandle, SteerSensEditId, buf); sprintf(buf, "%f", DeadZoneVal); GfuiEditboxSetString(scrHandle, DeadZoneEditId, buf); GfuiVisibilitySet(scrHandle, MouseCalButton, displayMouseCal); GfuiVisibilitySet(scrHandle, JoyCalButton, displayJoyCal); } static void onFocusLost(void * /* dummy */) { updateButtonText(); } static int CurrentCmd; static int InputWaited = 0; static int onKeyAction(unsigned char key, int /* modifier */, int state) { char *name; if (!InputWaited || (state == GFUI_KEY_UP)) { return 0; } if (key == 27) { /* escape */ Cmd[CurrentCmd].ref.index = -1; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_NOT_AFFECTED; GfParmSetStr(PrefHdle, CurrentSection, Cmd[CurrentCmd].name, ""); } else { name = GfctrlGetNameByRef(GFCTRL_TYPE_KEYBOARD, (int)key); Cmd[CurrentCmd].ref.index = (int)key; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_KEYBOARD; GfParmSetStr(PrefHdle, CurrentSection, Cmd[CurrentCmd].name, name); } glutIdleFunc(GfuiIdle); InputWaited = 0; updateButtonText(); return 1; } static int onSKeyAction(int key, int /* modifier */, int state) { char *name; if (!InputWaited || (state == GFUI_KEY_UP)) { return 0; } name = GfctrlGetNameByRef(GFCTRL_TYPE_SKEYBOARD, key); Cmd[CurrentCmd].ref.index = key; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_SKEYBOARD; GfParmSetStr(PrefHdle, CurrentSection, Cmd[CurrentCmd].name, name); glutIdleFunc(GfuiIdle); InputWaited = 0; updateButtonText(); return 1; } static int getMovedAxis(void) { int i; int Index = -1; float maxDiff = 0.3; for (i = 0; i < MAX_AXES * NUM_JOY; i++) { if (maxDiff < fabs(ax[i] - axCenter[i])) { maxDiff = fabs(ax[i] - axCenter[i]); Index = i; } } return Index; } static void Idle(void) { int mask; int b, i; int index; char *str; int axis; GfctrlMouseGetCurrent(&mouseInfo); /* Check for a mouse button pressed */ for (i = 0; i < 3; i++) { if (mouseInfo.edgedn[i]) { glutIdleFunc(GfuiIdle); InputWaited = 0; str = GfctrlGetNameByRef(GFCTRL_TYPE_MOUSE_BUT, i); Cmd[CurrentCmd].ref.index = i; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_MOUSE_BUT; GfuiButtonSetText (scrHandle, Cmd[CurrentCmd].Id, str); glutPostRedisplay(); return; } } /* Check for a mouse axis moved */ for (i = 0; i < 4; i++) { if (mouseInfo.ax[i] > 20.0) { glutIdleFunc(GfuiIdle); InputWaited = 0; str = GfctrlGetNameByRef(GFCTRL_TYPE_MOUSE_AXIS, i); Cmd[CurrentCmd].ref.index = i; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_MOUSE_AXIS; GfuiButtonSetText (scrHandle, Cmd[CurrentCmd].Id, str); glutPostRedisplay(); return; } } /* Check for a Joystick button pressed */ for (index = 0; index < NUM_JOY; index++) { if (js[index]) { js[index]->read(&b, &ax[index * MAX_AXES]); /* Joystick buttons */ for (i = 0, mask = 1; i < 32; i++, mask *= 2) { if (((b & mask) != 0) && ((rawb[index] & mask) == 0)) { /* Button i fired */ glutIdleFunc(GfuiIdle); InputWaited = 0; str = GfctrlGetNameByRef(GFCTRL_TYPE_JOY_BUT, i + 32 * index); Cmd[CurrentCmd].ref.index = i + 32 * index; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_JOY_BUT; GfuiButtonSetText (scrHandle, Cmd[CurrentCmd].Id, str); glutPostRedisplay(); rawb[index] = b; return; } } rawb[index] = b; } } /* detect joystick movement */ axis = getMovedAxis(); if (axis != -1) { glutIdleFunc(GfuiIdle); InputWaited = 0; Cmd[CurrentCmd].ref.type = GFCTRL_TYPE_JOY_AXIS; Cmd[CurrentCmd].ref.index = axis; str = GfctrlGetNameByRef(GFCTRL_TYPE_JOY_AXIS, axis); GfuiButtonSetText (scrHandle, Cmd[CurrentCmd].Id, str); glutPostRedisplay(); return; } } static void onPush(void *vi) { int index; long i = (long)vi; CurrentCmd = i; GfuiButtonSetText (scrHandle, Cmd[i].Id, ""); Cmd[i].ref.index = -1; Cmd[i].ref.type = GFCTRL_TYPE_NOT_AFFECTED; GfParmSetStr(PrefHdle, CurrentSection, Cmd[i].name, ""); if (Cmd[CurrentCmd].keyboardPossible) { InputWaited = 1; } glutIdleFunc(Idle); GfctrlMouseInitCenter(); memset(&mouseInfo, 0, sizeof(mouseInfo)); GfctrlMouseGetCurrent(&mouseInfo); for (index = 0; index < NUM_JOY; index++) { if (js[index]) { js[index]->read(&rawb[index], &ax[index * MAX_AXES]); /* initial value */ } } memcpy(axCenter, ax, sizeof(axCenter)); } static void onActivate(void * /* dummy */) { int cmd; char *prm; tCtrlRef *ref; if (ReloadValues) { sprintf(buf, "%s%s", GetLocalDir(), HM_PREF_FILE); PrefHdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); /* Mouse Settings */ for (cmd = 0; cmd < maxCmd; cmd++) { prm = GfctrlGetNameByRef(Cmd[cmd].ref.type, Cmd[cmd].ref.index); if (!prm) { prm = "---"; } prm = GfParmGetStr(PrefHdle, HM_SECT_MOUSEPREF, Cmd[cmd].name, prm); prm = GfParmGetStr(PrefHdle, CurrentSection, Cmd[cmd].name, prm); ref = GfctrlGetRefByName(prm); Cmd[cmd].ref.type = ref->type; Cmd[cmd].ref.index = ref->index; if (Cmd[cmd].minName) { Cmd[cmd].min = GfParmGetNum(PrefHdle, HM_SECT_MOUSEPREF, Cmd[cmd].minName, NULL, Cmd[cmd].min); Cmd[cmd].min = GfParmGetNum(PrefHdle, CurrentSection, Cmd[cmd].minName, NULL, Cmd[cmd].min); } if (Cmd[cmd].maxName) { Cmd[cmd].max = GfParmGetNum(PrefHdle, HM_SECT_MOUSEPREF, Cmd[cmd].maxName, NULL, Cmd[cmd].max); Cmd[cmd].max = GfParmGetNum(PrefHdle, CurrentSection, Cmd[cmd].maxName, NULL, Cmd[cmd].max); } if (Cmd[cmd].powName) { Cmd[cmd].pow = GfParmGetNum(PrefHdle, HM_SECT_MOUSEPREF, Cmd[cmd].powName, NULL, Cmd[cmd].pow); Cmd[cmd].pow = GfParmGetNum(PrefHdle, CurrentSection, Cmd[cmd].powName, NULL, Cmd[cmd].pow); } } SteerSensVal = GfParmGetNum(PrefHdle, HM_SECT_MOUSEPREF, HM_ATT_STEER_SENS, NULL, 0); SteerSensVal = GfParmGetNum(PrefHdle, CurrentSection, HM_ATT_STEER_SENS, NULL, SteerSensVal); DeadZoneVal = GfParmGetNum(PrefHdle, HM_SECT_MOUSEPREF, HM_ATT_STEER_DEAD, NULL, 0); DeadZoneVal = GfParmGetNum(PrefHdle, CurrentSection, HM_ATT_STEER_DEAD, NULL, DeadZoneVal); } updateButtonText(); } static void DevCalibrate(void *menu) { ReloadValues = 0; GfuiScreenActivate(menu); } void * TorcsControlMenuInit(void *prevMenu, int idx) { int x, y, x2, dy, i; int index; ReloadValues = 1; sprintf(CurrentSection, "%s/%d", HM_SECT_DRVPREF, idx); prevHandle = prevMenu; sprintf(buf, "%s%s", GetLocalDir(), HM_PREF_FILE); PrefHdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); if (scrHandle) { return scrHandle; } for (index = 0; index < NUM_JOY; index++) { if (js[index] == NULL) { js[index] = new jsJoystick(index); } if (js[index]->notWorking()) { /* don't configure the joystick */ js[index] = NULL; } } scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, onActivate, NULL, (tfuiCallback)NULL, 1); GfuiTitleCreate(scrHandle, "Control Configuration", 0); GfuiScreenAddBgImg(scrHandle, "data/img/splash-mouseconf.png"); GfuiMenuDefaultKeysAdd(scrHandle); x = 10; x2 = 210; y = 340; dy = 30; for (i = 0; i < maxCmd; i++) { GfuiLabelCreate(scrHandle, Cmd[i].name, GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0); Cmd[i].Id = GfuiButtonStateCreate (scrHandle, "MOUSE_MIDDLE_BUTTON", GFUI_FONT_MEDIUM_C, x+x2, y, 0, GFUI_ALIGN_HC_VB, GFUI_MOUSE_DOWN, (void*)i, onPush, NULL, (tfuiCallback)NULL, onFocusLost); y -= dy; if (i == (maxCmd / 2 - 1)) { x = 320; y = 340; x2 = 220; } } GfuiLabelCreate(scrHandle, "Steer Sensibility", GFUI_FONT_MEDIUM, 30, 90, GFUI_ALIGN_HL_VB, 0); SteerSensEditId = GfuiEditboxCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, 200, 90, 80, 8, NULL, (tfuiCallback)NULL, onSteerSensChange); GfuiLabelCreate(scrHandle, "Steer Dead Zone", GFUI_FONT_MEDIUM, 340, 90, GFUI_ALIGN_HL_VB, 0); DeadZoneEditId = GfuiEditboxCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, 510, 90, 80, 8, NULL, (tfuiCallback)NULL, onDeadZoneChange); GfuiAddKey(scrHandle, 13, "Save", NULL, onSave, NULL); GfuiButtonCreate(scrHandle, "Save", GFUI_FONT_LARGE, 160, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, NULL, onSave, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); MouseCalButton = GfuiButtonCreate(scrHandle, "Calibrate", GFUI_FONT_LARGE, 320, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, MouseCalMenuInit(scrHandle, Cmd, maxCmd), DevCalibrate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); JoyCalButton = GfuiButtonCreate(scrHandle, "Calibrate", GFUI_FONT_LARGE, 320, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, JoyCalMenuInit(scrHandle, Cmd, maxCmd), DevCalibrate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiAddKey(scrHandle, 27, "Cancel", prevMenu, GfuiScreenActivate, NULL); GfuiButtonCreate(scrHandle, "Cancel", GFUI_FONT_LARGE, 480, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, prevMenu, GfuiScreenActivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiKeyEventRegister(scrHandle, onKeyAction); GfuiSKeyEventRegister(scrHandle, onSKeyAction); return scrHandle; }