/***************************************************************************
driverselect.cpp -- drivers interactive selection
-------------------
created : Mon Aug 16 20:40:44 CEST 1999
copyright : (C) 1999 by Eric Espie
email : torcs@free.fr
version : $Id: driverselect.cpp,v 1.5 2005/02/01 15:55:52 berniw 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
This is a set of tools useful for race managers.
@ingroup racemantools
@author Eric Espie
@version $Id: driverselect.cpp,v 1.5 2005/02/01 15:55:52 berniw Exp $
*/
#include
#include
#include
#include
#ifdef WIN32
#include
#endif
#include
#include
#include
#include
#include
#include
static void *scrHandle;
static tRmDrvSelect *ds;
static int selectedScrollList, unselectedScrollList;
static int FocDrvLabelId;
static int PickDrvNameLabelId;
static int PickDrvCarLabelId;
static int PickDrvCategoryLabelId;
static float aColor[] = {1.0, 0.0, 0.0, 1.0};
static char buf[256];
static char path[256];
static int nbSelectedDrivers;
static int nbMaxSelectedDrivers;
typedef struct DrvElt
{
int index;
char *dname;
char *name;
int sel;
int human;
void *car;
GF_TAILQ_ENTRY(struct DrvElt) link;
} tDrvElt;
GF_TAILQ_HEAD(DrvListHead, tDrvElt);
tDrvListHead DrvList;
static void rmFreeDrvList(void);
static void
rmdsActivate(void * /* notused */)
{
/* call display function of graphic */
}
static void
rmdsDeactivate(void *screen)
{
rmFreeDrvList();
GfuiScreenRelease(scrHandle);
if (screen) {
GfuiScreenActivate(screen);
}
}
static void
rmdsSetFocus(void * /* dummy */)
{
char *name;
tDrvElt *curDrv;
name = GfuiScrollListGetSelectedElement(scrHandle, selectedScrollList, (void**)&curDrv);
if (name) {
GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, curDrv->dname);
GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, curDrv->index);
GfuiLabelSetText(scrHandle, FocDrvLabelId, curDrv->name);
}
}
static void
rmdsSelect(void * /* dummy */)
{
char *name;
tDrvElt *curDrv;
int index;
sprintf(buf, "%s", RM_SECT_DRIVERS);
GfParmListClean(ds->param, buf);
name = GfuiScrollListExtractElement(scrHandle, selectedScrollList, 0, (void**)&curDrv);
index = 1;
while (name != NULL) {
sprintf(buf, "%s/%d", RM_SECT_DRIVERS, index);
GfParmSetNum(ds->param, buf, RM_ATTR_IDX, (char*)NULL, curDrv->index);
GfParmSetStr(ds->param, buf, RM_ATTR_MODULE, curDrv->dname);
index++;
name = GfuiScrollListExtractElement(scrHandle, selectedScrollList, 0, (void**)&curDrv);
}
rmdsDeactivate(ds->nextScreen);
}
static void
rmMove(void *vd)
{
GfuiScrollListMoveSelectedElement(scrHandle, selectedScrollList, (long)vd);
GfuiScrollListMoveSelectedElement(scrHandle, unselectedScrollList, (long)vd);
}
static void
rmdsClickOnDriver(void * /* dummy */)
{
char *name;
tDrvElt *curDrv;
void *robhdle;
name = GfuiScrollListGetSelectedElement(scrHandle, selectedScrollList, (void**)&curDrv);
if (!name) {
name = GfuiScrollListGetSelectedElement(scrHandle, unselectedScrollList, (void**)&curDrv);
}
if (name) {
GfuiLabelSetText(scrHandle, PickDrvNameLabelId, curDrv->name);
/* search driver infos */
sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), curDrv->dname, curDrv->dname);
robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
if (!robhdle) {
sprintf(buf, "drivers/%s/%s.xml", curDrv->dname, curDrv->dname);
robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
}
if (robhdle != NULL) {
sprintf(buf, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, curDrv->index);
GfuiLabelSetText(scrHandle, PickDrvCarLabelId, GfParmGetName(curDrv->car));
GfuiLabelSetText(scrHandle, PickDrvCategoryLabelId, GfParmGetStr(curDrv->car, SECT_CAR, PRM_CATEGORY, ""));
GfParmReleaseHandle(robhdle);
}
}
}
static void
rmSelectDeselect(void * /* dummy */ )
{
char *name;
int src, dst;
tDrvElt *curDrv;
char *cardllname;
int robotIdx;
int sel;
sel = 0;
name = 0;
if (nbSelectedDrivers < nbMaxSelectedDrivers) {
src = unselectedScrollList;
name = GfuiScrollListExtractSelectedElement(scrHandle, src, (void**)&curDrv);
if (name) {
dst = selectedScrollList;
GfuiScrollListInsertElement(scrHandle, dst, name, 100, (void*)curDrv);
nbSelectedDrivers++;
}
}
if (!name) {
sel = 1;
src = selectedScrollList;
name = GfuiScrollListExtractSelectedElement(scrHandle, src, (void**)&curDrv);
if (name) {
dst = unselectedScrollList;
if (curDrv->human) {
GfuiScrollListInsertElement(scrHandle, dst, name, 0, (void*)curDrv);
} else {
GfuiScrollListInsertElement(scrHandle, dst, name, 100, (void*)curDrv);
}
nbSelectedDrivers--;
} else {
return;
}
}
cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
if (sel) {
cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) {
/* the focused element was deselected select a new one */
name = GfuiScrollListGetElement(scrHandle, selectedScrollList, 0, (void**)&curDrv);
if (name) {
GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, curDrv->dname);
GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, curDrv->index);
GfuiLabelSetText(scrHandle, FocDrvLabelId, curDrv->name);
} else {
GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
GfuiLabelSetText(scrHandle, FocDrvLabelId, "");
}
}
} else {
if ((strlen(cardllname) == 0) || (curDrv->human)) {
GfParmSetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, curDrv->dname);
GfParmSetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, curDrv->index);
GfuiLabelSetText(scrHandle, FocDrvLabelId, curDrv->name);
}
}
rmdsClickOnDriver(NULL);
}
static void
rmdsAddKeys(void)
{
GfuiAddKey(scrHandle, 27, "Cancel Selection", ds->prevScreen, rmdsDeactivate, NULL);
GfuiAddKey(scrHandle, 13, "Accept Selection", NULL, rmdsSelect, NULL);
GfuiAddSKey(scrHandle, GLUT_KEY_F1, "Help", scrHandle, GfuiHelpScreen, NULL);
GfuiAddSKey(scrHandle, GLUT_KEY_F12, "Screen-Shot", NULL, GfuiScreenShot, NULL);
GfuiAddKey(scrHandle, '-', "Move Up", (void*)-1, rmMove, NULL);
GfuiAddKey(scrHandle, '+', "Move Down", (void*)1, rmMove, NULL);
GfuiAddKey(scrHandle, ' ', "Select/Deselect", NULL, rmSelectDeselect, NULL);
GfuiAddKey(scrHandle, 'f', "Set Focus", NULL, rmdsSetFocus, NULL);
}
/** Interactive Drivers list selection
@param vs Pointer on tRmDrvSelect structure (cast to void)
@warning The race manager params are modified but not saved.
*/
void
RmDriversSelect(void *vs)
{
tModList *list;
tModList *curmod;
char dname[256];
char *sp;
char *cardllname;
int i, index;
tDrvElt *curDrv;
int nCars, robotIdx;
void *robhdle;
struct stat st;
char *carName;
void *carhdle;
int human;
#define B_BASE 380
#define B_HT 30
ds = (tRmDrvSelect*)vs;
GF_TAILQ_INIT(&DrvList);
scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, rmdsActivate, NULL, (tfuiCallback)NULL, 1);
GfuiScreenAddBgImg(scrHandle, "data/img/splash-qrdrv.png");
GfuiTitleCreate(scrHandle, "Select Drivers", sizeof("Select Drivers"));
GfuiLabelCreate(scrHandle,
"Selected",
GFUI_FONT_LARGE,
120, 400, GFUI_ALIGN_HC_VB,
0);
GfuiLabelCreate(scrHandle,
"Not Selected",
GFUI_FONT_LARGE,
496, 400, GFUI_ALIGN_HC_VB,
0);
selectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 20, 80, GFUI_ALIGN_HL_VB,
200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver);
unselectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 396, 80, GFUI_ALIGN_HL_VB,
200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver);
GfuiButtonCreate(scrHandle, "Accept", GFUI_FONT_LARGE, 210, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
NULL, rmdsSelect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
GfuiButtonCreate(scrHandle, "Cancel", GFUI_FONT_LARGE, 430, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
ds->prevScreen, rmdsDeactivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
GfuiButtonCreate(scrHandle, "Move Up", GFUI_FONT_MEDIUM, 320, B_BASE, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
(void*)-1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
GfuiButtonCreate(scrHandle, "Move Down", GFUI_FONT_MEDIUM, 320, B_BASE - B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
(void*)1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
GfuiButtonCreate(scrHandle, "(De)Select", GFUI_FONT_MEDIUM, 320, B_BASE - 2 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
(void*)0, rmSelectDeselect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
GfuiButtonCreate(scrHandle, "Set Focus", GFUI_FONT_MEDIUM, 320, B_BASE - 3 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
NULL, rmdsSetFocus, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
list = (tModList *)NULL;
sprintf(buf, "%sdrivers", GetLibDir ());
GfModInfoDir(CAR_IDENT, buf, 1, &list);
curmod = list;
if (curmod != NULL) {
do {
curmod = curmod->next;
for (i = 0; i < MAX_MOD_ITF; i++) {
if (curmod->modInfo[i].name) {
sp = strrchr(curmod->sopath, '/');
if (sp == NULL) {
sp = curmod->sopath;
} else {
sp++;
}
strcpy(dname, sp);
dname[strlen(dname) - strlen(DLLEXT) - 1] = 0; /* cut .so or .dll */
sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), dname, dname);
robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
if (!robhdle) {
sprintf(buf, "drivers/%s/%s.xml", dname, dname);
robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
}
sprintf(path, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, curmod->modInfo[i].index);
carName = GfParmGetStr(robhdle, path, ROB_ATTR_CAR, "");
if (strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT)) {
human = 1;
} else {
human = 0;
}
sprintf(path, "cars/%s/%s.xml", carName, carName);
if (!stat(path, &st)) {
carhdle = GfParmReadFile(path, GFPARM_RMODE_STD);
if (carhdle) {
curDrv = (tDrvElt*)calloc(1, sizeof(tDrvElt));
curDrv->index = curmod->modInfo[i].index;
curDrv->dname = strdup(dname);
curDrv->name = strdup(curmod->modInfo[i].name);
curDrv->car = carhdle;
if (human) {
curDrv->human = 1;
GF_TAILQ_INSERT_HEAD(&DrvList, curDrv, link);
} else {
curDrv->human = 0;
GF_TAILQ_INSERT_TAIL(&DrvList, curDrv, link);
}
} else {
GfOut("Driver %s not selected because car %s is not readable\n", curmod->modInfo[i].name, carName);
}
} else {
GfOut("Driver %s not selected because car %s is not present\n", curmod->modInfo[i].name, carName);
}
GfParmReleaseHandle(robhdle);
}
}
} while (curmod != list);
}
nbSelectedDrivers = 0;
nbMaxSelectedDrivers = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0);
nCars = GfParmGetEltNb(ds->param, RM_SECT_DRIVERS);
index = 1;
for (i = 1; i < nCars+1; i++) {
sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i);
cardllname = GfParmGetStr(ds->param, dname, RM_ATTR_MODULE, "");
robotIdx = (int)GfParmGetNum(ds->param, dname, RM_ATTR_IDX, (char*)NULL, 0);
curDrv = GF_TAILQ_FIRST(&DrvList);
if (curDrv != NULL) {
do {
if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) {
if (nbSelectedDrivers < nbMaxSelectedDrivers) {
GfuiScrollListInsertElement(scrHandle, selectedScrollList, curDrv->name, index, (void*)curDrv);
curDrv->sel = index++;
nbSelectedDrivers++;
}
break;
}
} while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL);
}
}
curDrv = GF_TAILQ_FIRST(&DrvList);
if (curDrv != NULL) {
do {
if (curDrv->sel == 0) {
GfuiScrollListInsertElement(scrHandle, unselectedScrollList, curDrv->name, 1000, (void*)curDrv);
}
} while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL);
}
GfuiLabelCreate(scrHandle, "Focused:", GFUI_FONT_MEDIUM, 320, B_BASE - 5 * B_HT, GFUI_ALIGN_HC_VB, 0);
cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0);
curDrv = GF_TAILQ_FIRST(&DrvList);
if (curDrv != NULL) {
do {
if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) {
break;
}
} while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL);
}
if (curDrv == NULL) {
curDrv = GF_TAILQ_FIRST(&DrvList);
}
if (curDrv == NULL) {
FocDrvLabelId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C,
320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
} else {
FocDrvLabelId = GfuiLabelCreate(scrHandle, curDrv->name, GFUI_FONT_MEDIUM_C,
320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
}
/* Picked Driver Info */
GfuiLabelCreate(scrHandle, "Driver:", GFUI_FONT_MEDIUM, 320, B_BASE - 7 * B_HT, GFUI_ALIGN_HC_VB, 0);
PickDrvNameLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C,
320, B_BASE - 7 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
GfuiLabelCreate(scrHandle, "Car:", GFUI_FONT_MEDIUM, 320, B_BASE - 8 * B_HT, GFUI_ALIGN_HC_VB, 0);
PickDrvCarLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C,
320, B_BASE - 8 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
GfuiLabelCreate(scrHandle, "Category:", GFUI_FONT_MEDIUM, 320, B_BASE - 9 * B_HT, GFUI_ALIGN_HC_VB, 0);
PickDrvCategoryLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C,
320, B_BASE - 9 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256);
GfuiMenuDefaultKeysAdd(scrHandle);
rmdsAddKeys();
GfuiScreenActivate(scrHandle);
}
static void
rmFreeDrvList(void)
{
tDrvElt *cur;
while ((cur = GF_TAILQ_FIRST(&DrvList)) != NULL) {
GF_TAILQ_REMOVE(&DrvList, cur, link);
free(cur->name);
free(cur->dname);
GfParmReleaseHandle(cur->car);
free(cur);
}
}