Index: code/sdl/sdl_input.c =================================================================== --- code/sdl/sdl_input.c (revision 1900) +++ code/sdl/sdl_input.c (working copy) @@ -576,6 +576,7 @@ { int i = 0; int total = 0; + char buf[ MAX_STRING_CHARS ] = { 0 }; if (stick != NULL) SDL_JoystickClose(stick); @@ -583,11 +584,6 @@ stick = NULL; memset(&stick_state, '\0', sizeof (stick_state)); - if( !in_joystick->integer ) { - Com_DPrintf( "Joystick is not active.\n" ); - return; - } - if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { Com_DPrintf("Calling SDL_Init(SDL_INIT_JOYSTICK)...\n"); @@ -601,9 +597,32 @@ total = SDL_NumJoysticks(); Com_DPrintf("%d possible joysticks\n", total); - for (i = 0; i < total; i++) + + // Print list and build cvar to allow ui to select joystick. + for (i = 0; i < total; i++) { + const char *newJoystickString = va( "\"%.61s\" ", SDL_JoystickName(i) ); + Com_DPrintf("[%d] %s\n", i, SDL_JoystickName(i)); + if( strlen( newJoystickString ) < (int)sizeof( buf ) - strlen( buf ) ) + Q_strcat( buf, sizeof( buf ), newJoystickString ); + else + Com_DPrintf( "Skipping joystick %s, buffer too small\n", SDL_JoystickName(i) ); + } + + if (*buf) { + // Remove space at the end of the string + buf[ strlen( buf ) - 1 ] = 0; + } + + Cvar_Get( "in_availableJoysticks", buf, CVAR_ROM ); + + if( !in_joystick->integer ) { + Com_DPrintf( "Joystick is not active.\n" ); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + return; + } + in_joystickNo = Cvar_Get( "in_joystickNo", "0", CVAR_ARCHIVE ); if( in_joystickNo->integer < 0 || in_joystickNo->integer >= total ) Cvar_Set( "in_joystickNo", "0" ); Index: code/q3_ui/ui_controls2.c =================================================================== --- code/q3_ui/ui_controls2.c (revision 1900) +++ code/q3_ui/ui_controls2.c (working copy) @@ -118,7 +118,7 @@ #define ID_ALWAYSRUN 36 #define ID_AUTOSWITCH 37 #define ID_MOUSESPEED 38 -#define ID_JOYENABLE 39 +#define ID_SELECTJOY 39 #define ID_JOYTHRESHOLD 40 #define ID_SMOOTHMOUSE 41 @@ -205,7 +205,7 @@ menuaction_s chat2; menuaction_s chat3; menuaction_s chat4; - menuradiobutton_s joyenable; + menutext_s selectjoy; menuslider_s joythreshold; int section; qboolean waitingforkey; @@ -270,8 +270,7 @@ {"m_pitch", 0, 0}, {"cg_autoswitch", 0, 0}, {"sensitivity", 0, 0}, - {"in_joystick", 0, 0}, - {"joy_threshold", 0, 0}, + {"in_joystickThreshold", 0, 0}, {"m_filter", 0, 0}, {"cl_freelook", 0, 0}, {NULL, 0, 0} @@ -320,7 +319,7 @@ (menucommon_s *)&s_controls.freelook, (menucommon_s *)&s_controls.centerview, (menucommon_s *)&s_controls.zoomview, - (menucommon_s *)&s_controls.joyenable, + (menucommon_s *)&s_controls.selectjoy, (menucommon_s *)&s_controls.joythreshold, NULL, }; @@ -718,6 +717,45 @@ /* ================= +Controls_DrawSmallText +================= +*/ +static void Controls_DrawSmallText( void *self ) +{ + menutext_s *text; + int x, y; + qboolean c; + + text = (menutext_s*) self; + + c = (Menu_ItemAtCursor( text->generic.parent ) == text); + + x = text->generic.x; + y = text->generic.y; + + if (c) + { + UI_FillRect( text->generic.left, text->generic.top, text->generic.right-text->generic.left+1, text->generic.bottom-text->generic.top+1, listbar_color ); + + UI_DrawString( x - SMALLCHAR_WIDTH, y, text->string, UI_RIGHT|UI_SMALLFONT, text_color_highlight ); + + UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite ); + } + else + { + if (text->generic.flags & QMF_GRAYED) + { + UI_DrawString( x - SMALLCHAR_WIDTH, y, text->string, UI_RIGHT|UI_SMALLFONT, text_color_disabled ); + } + else + { + UI_DrawString( x - SMALLCHAR_WIDTH, y, text->string, UI_RIGHT|UI_SMALLFONT, text_color_normal ); + } + } +} + +/* +================= Controls_StatusBar ================= */ @@ -808,8 +846,7 @@ s_controls.alwaysrun.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_run" ) ); s_controls.autoswitch.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cg_autoswitch" ) ); s_controls.sensitivity.curvalue = UI_ClampCvar( 2, 30, Controls_GetCvarValue( "sensitivity" ) ); - s_controls.joyenable.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "in_joystick" ) ); - s_controls.joythreshold.curvalue = UI_ClampCvar( 0.05f, 0.75f, Controls_GetCvarValue( "joy_threshold" ) ); + s_controls.joythreshold.curvalue = UI_ClampCvar( 0.05f, 0.75f, Controls_GetCvarValue( "in_joystickThreshold" ) ); s_controls.freelook.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_freelook" ) ); } @@ -850,10 +887,8 @@ trap_Cvar_SetValue( "cl_run", s_controls.alwaysrun.curvalue ); trap_Cvar_SetValue( "cg_autoswitch", s_controls.autoswitch.curvalue ); trap_Cvar_SetValue( "sensitivity", s_controls.sensitivity.curvalue ); - trap_Cvar_SetValue( "in_joystick", s_controls.joyenable.curvalue ); - trap_Cvar_SetValue( "joy_threshold", s_controls.joythreshold.curvalue ); + trap_Cvar_SetValue( "in_joystickThreshold", s_controls.joythreshold.curvalue ); trap_Cvar_SetValue( "cl_freelook", s_controls.freelook.curvalue ); - trap_Cmd_ExecuteText( EXEC_APPEND, "in_restart\n" ); } /* @@ -884,8 +919,9 @@ s_controls.alwaysrun.curvalue = Controls_GetCvarDefault( "cl_run" ); s_controls.autoswitch.curvalue = Controls_GetCvarDefault( "cg_autoswitch" ); s_controls.sensitivity.curvalue = Controls_GetCvarDefault( "sensitivity" ); - s_controls.joyenable.curvalue = Controls_GetCvarDefault( "in_joystick" ); - s_controls.joythreshold.curvalue = Controls_GetCvarDefault( "joy_threshold" ); + trap_Cvar_SetValue("in_joystick", 0); + trap_Cvar_SetValue("in_joystickNo", 0); + s_controls.joythreshold.curvalue = Controls_GetCvarDefault( "in_joystickThreshold" ); s_controls.freelook.curvalue = Controls_GetCvarDefault( "cl_freelook" ); } @@ -1115,13 +1151,19 @@ case ID_SMOOTHMOUSE: case ID_ALWAYSRUN: case ID_AUTOSWITCH: - case ID_JOYENABLE: case ID_JOYTHRESHOLD: if (event == QM_ACTIVATED) { s_controls.changesmade = qtrue; } break; + + case ID_SELECTJOY: + if (event == QM_ACTIVATED) + { + UI_JoystickMenu(); + } + break; } } @@ -1532,13 +1574,15 @@ s_controls.chat4.generic.ownerdraw = Controls_DrawKeyBinding; s_controls.chat4.generic.id = ID_CHAT4; - s_controls.joyenable.generic.type = MTYPE_RADIOBUTTON; - s_controls.joyenable.generic.flags = QMF_SMALLFONT; - s_controls.joyenable.generic.x = SCREEN_WIDTH/2; - s_controls.joyenable.generic.name = "joystick"; - s_controls.joyenable.generic.id = ID_JOYENABLE; - s_controls.joyenable.generic.callback = Controls_MenuEvent; - s_controls.joyenable.generic.statusbar = Controls_StatusBar; + s_controls.selectjoy.generic.type = MTYPE_PTEXT; + s_controls.selectjoy.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_controls.selectjoy.generic.x = SCREEN_WIDTH/2; + s_controls.selectjoy.generic.id = ID_SELECTJOY; + s_controls.selectjoy.generic.callback = Controls_MenuEvent; + s_controls.selectjoy.generic.ownerdraw = Controls_DrawSmallText; + s_controls.selectjoy.string = "select joystick..."; + s_controls.selectjoy.color = text_color_normal; + s_controls.selectjoy.style = UI_RIGHT|UI_SMALLFONT; s_controls.joythreshold.generic.type = MTYPE_SLIDER; s_controls.joythreshold.generic.x = SCREEN_WIDTH/2; @@ -1578,7 +1622,7 @@ Menu_AddItem( &s_controls.menu, &s_controls.freelook ); Menu_AddItem( &s_controls.menu, &s_controls.centerview ); Menu_AddItem( &s_controls.menu, &s_controls.zoomview ); - Menu_AddItem( &s_controls.menu, &s_controls.joyenable ); + Menu_AddItem( &s_controls.menu, &s_controls.selectjoy ); Menu_AddItem( &s_controls.menu, &s_controls.joythreshold ); Menu_AddItem( &s_controls.menu, &s_controls.alwaysrun ); Index: code/q3_ui/ui_local.h =================================================================== --- code/q3_ui/ui_local.h (revision 1900) +++ code/q3_ui/ui_local.h (working copy) @@ -362,6 +362,12 @@ extern void Controls_Cache( void ); // +// ui_joystick.c +// +void UI_JoystickMenu( void ); +void UI_Joystick_Cache( void ); + +// // ui_demo2.c // extern void UI_DemosMenu( void ); Index: code/q3_ui/ui_atoms.c =================================================================== --- code/q3_ui/ui_atoms.c (revision 1900) +++ code/q3_ui/ui_atoms.c (working copy) @@ -958,6 +958,7 @@ PlayerModel_Cache(); PlayerSettings_Cache(); Controls_Cache(); + UI_Joystick_Cache(); Demos_Cache(); UI_CinematicsMenu_Cache(); Preferences_Cache(); Index: Makefile =================================================================== --- Makefile (revision 1900) +++ Makefile (working copy) @@ -1975,6 +1975,7 @@ $(B)/baseq3/ui/ui_display.o \ $(B)/baseq3/ui/ui_gameinfo.o \ $(B)/baseq3/ui/ui_ingame.o \ + $(B)/baseq3/ui/ui_joystick.o \ $(B)/baseq3/ui/ui_loadconfig.o \ $(B)/baseq3/ui/ui_menu.o \ $(B)/baseq3/ui/ui_mfield.o \ Index: code/q3_ui/ui_joystick.c =================================================================== --- code/q3_ui/ui_joystick.c (revision 0) +++ code/q3_ui/ui_joystick.c (revision 0) @@ -0,0 +1,382 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code 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. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake III Arena source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// +/* +======================================================================= + +JOYSTICK SELECT MENU + +======================================================================= +*/ + +#include "ui_local.h" + +#define MAX_JOYSTICKS 16 + +#define JOY_MENU_VERTICAL_SPACING 16 + +#define ART_BACK0 "menu/art/back_0" +#define ART_BACK1 "menu/art/back_1" +#define ART_FRAMEL "menu/art/frame2_l" +#define ART_FRAMER "menu/art/frame1_r" + +#define ID_JOYSTICK 10 +#define ID_BACK ID_JOYSTICK + MAX_JOYSTICKS + + +typedef struct { + menuframework_s menu; + + menutext_s banner; + menubitmap_s framel; + menubitmap_s framer; + + menutext_s joysticks[MAX_JOYSTICKS]; + + menubitmap_s back; + + char joystickNames[ MAX_JOYSTICKS ][ 61 ]; + int numJoysticks; + + int originalJoystick; + qboolean changed; + +} joystickMenu_t; + +static joystickMenu_t joystickMenu; + + +/* +=============== +UI_JoystickMenu_Event +=============== +*/ +static void UI_JoystickMenu_Event( void *ptr, int event ) { + if( event != QM_ACTIVATED ) { + return; + } + + if (((menucommon_s*)ptr)->id >= ID_JOYSTICK && ((menucommon_s*)ptr)->id < ID_JOYSTICK + MAX_JOYSTICKS) { + int joystick = ((menucommon_s*)ptr)->id - ID_JOYSTICK; + int i; + + if (joystick == 0) { + // Disable joystick + trap_Cvar_SetValue("in_joystick", 0); + trap_Cvar_SetValue("in_joystickNo", 0); + } else { + // Enable joystick + trap_Cvar_SetValue("in_joystick", 1); + trap_Cvar_SetValue("in_joystickNo", joystick-1); + } + + // Disable last selected joystick. + for (i = 0; i < MAX_JOYSTICKS; i++) { + joystickMenu.joysticks[i].generic.flags |= QMF_PULSEIFFOCUS; + joystickMenu.joysticks[i].generic.flags &= ~(QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); + } + + // Select joystick. + ((menucommon_s*)ptr)->flags &= ~QMF_PULSEIFFOCUS; + ((menucommon_s*)ptr)->flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); + + joystickMenu.changed = (joystick != joystickMenu.originalJoystick); + return; + } + + switch( ((menucommon_s*)ptr)->id ) { + + case ID_BACK: + if (joystickMenu.changed) { + trap_Cmd_ExecuteText( EXEC_APPEND, "in_restart\n" ); + } + + UI_PopMenu(); + break; + } +} + +/* +============ +UI_TokenizeString + +Clone of Cmd_TokenizeString that doesn't use global variables. +============ +*/ +static void UI_TokenizeString( const char *text_in, char *cmd_tokenized, + int *cmd_argc, char **cmd_argv, qboolean ignoreQuotes ) +{ + const char *text; + char *textOut; + + // clear previous args + *cmd_argc = 0; + + if ( !text_in ) { + return; + } + + text = text_in; + textOut = cmd_tokenized; + + while ( 1 ) { + if ( *cmd_argc == MAX_STRING_TOKENS ) { + return; // this is usually something malicious + } + + while ( 1 ) { + // skip whitespace + while ( *text && *text <= ' ' ) { + text++; + } + if ( !*text ) { + return; // all tokens parsed + } + + // skip // comments + if ( text[0] == '/' && text[1] == '/' ) { + return; // all tokens parsed + } + + // skip /* */ comments + if ( text[0] == '/' && text[1] =='*' ) { + while ( *text && ( text[0] != '*' || text[1] != '/' ) ) { + text++; + } + if ( !*text ) { + return; // all tokens parsed + } + text += 2; + } else { + break; // we are ready to parse a token + } + } + + // handle quoted strings + // NOTE TTimo this doesn't handle \" escaping + if ( !ignoreQuotes && *text == '"' ) { + cmd_argv[*cmd_argc] = textOut; + (*cmd_argc)++; + text++; + while ( *text && *text != '"' ) { + *textOut++ = *text++; + } + *textOut++ = 0; + if ( !*text ) { + return; // all tokens parsed + } + text++; + continue; + } + + // regular token + cmd_argv[*cmd_argc] = textOut; + (*cmd_argc)++; + + // skip until whitespace, quote, or command + while ( *text > ' ' ) { + if ( !ignoreQuotes && text[0] == '"' ) { + break; + } + + if ( text[0] == '/' && text[1] == '/' ) { + break; + } + + // skip /* */ comments + if ( text[0] == '/' && text[1] =='*' ) { + break; + } + + *textOut++ = *text++; + } + + *textOut++ = 0; + + if ( !*text ) { + return; // all tokens parsed + } + } +} + +/* +=============== +UI_Joystick_GetNames +=============== +*/ +static void UI_Joystick_GetNames( void ) { + char joybuf[ MAX_STRING_CHARS ]; + int i; + char *cmd_argv[MAX_STRING_TOKENS]; // points into cmd_tokenized + char cmd_tokenized[BIG_INFO_STRING+MAX_STRING_TOKENS]; // will have 0 bytes inserted + + // Get quoted string of joystick names. + Q_strncpyz(joybuf, UI_Cvar_VariableString("in_availableJoysticks"), sizeof(joybuf)); + + // Option to disable joystick + Q_strncpyz(joystickMenu.joystickNames[0], "None", sizeof (joystickMenu.joystickNames[0])); + + if (*joybuf) { + // Seperate joystick names + UI_TokenizeString( joybuf, cmd_tokenized, &joystickMenu.numJoysticks, cmd_argv, qfalse ); + + // Joysticks plus disable option + joystickMenu.numJoysticks += 1; + + // Get names of joysticks + for (i = 1; i < joystickMenu.numJoysticks; i++) { + Q_strncpyz(joystickMenu.joystickNames[i], cmd_argv[i-1], sizeof (joystickMenu.joystickNames[i])); + } + } else { + joystickMenu.numJoysticks = i = 1; + } + + // Set default text for empty slots. + for ( ; i < MAX_JOYSTICKS; i++) { + Q_strncpyz(joystickMenu.joystickNames[i], "Unavailable", sizeof (joystickMenu.joystickNames[i])); + } +} + +/* +=============== +UI_Joystick_MenuInit +=============== +*/ +static void UI_Joystick_MenuInit( void ) { + int y; + int i; + int joystick; + + UI_Joystick_Cache(); + + memset( &joystickMenu, 0, sizeof(joystickMenu) ); + + UI_Joystick_GetNames(); + + joystickMenu.menu.wrapAround = qtrue; + joystickMenu.menu.fullscreen = qtrue; + + joystickMenu.banner.generic.type = MTYPE_BTEXT; + joystickMenu.banner.generic.x = 320; + joystickMenu.banner.generic.y = 16; + joystickMenu.banner.string = "SELECT JOYSTICK"; + joystickMenu.banner.color = color_white; + joystickMenu.banner.style = UI_CENTER; + + joystickMenu.framel.generic.type = MTYPE_BITMAP; + joystickMenu.framel.generic.name = ART_FRAMEL; + joystickMenu.framel.generic.flags = QMF_INACTIVE; + joystickMenu.framel.generic.x = 0; + joystickMenu.framel.generic.y = 78; + joystickMenu.framel.width = 256; + joystickMenu.framel.height = 329; + + joystickMenu.framer.generic.type = MTYPE_BITMAP; + joystickMenu.framer.generic.name = ART_FRAMER; + joystickMenu.framer.generic.flags = QMF_INACTIVE; + joystickMenu.framer.generic.x = 376; + joystickMenu.framer.generic.y = 76; + joystickMenu.framer.width = 256; + joystickMenu.framer.height = 334; + + y = (SCREEN_HEIGHT - MAX_JOYSTICKS * JOY_MENU_VERTICAL_SPACING) * 0.5f; + + for (i = 0; i < MAX_JOYSTICKS; i++) { + joystickMenu.joysticks[i].generic.type = MTYPE_PTEXT; + joystickMenu.joysticks[i].generic.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS|QMF_SMALLFONT; + joystickMenu.joysticks[i].generic.x = 320; + joystickMenu.joysticks[i].generic.y = y; + joystickMenu.joysticks[i].generic.id = ID_JOYSTICK+i; + joystickMenu.joysticks[i].generic.callback = UI_JoystickMenu_Event; + joystickMenu.joysticks[i].string = joystickMenu.joystickNames[i]; + joystickMenu.joysticks[i].color = color_red; + joystickMenu.joysticks[i].style = UI_CENTER|UI_SMALLFONT; + + if (i >= joystickMenu.numJoysticks) { + joystickMenu.joysticks[i].generic.flags |= QMF_GRAYED; + } + + y += JOY_MENU_VERTICAL_SPACING; + } + + joystickMenu.back.generic.type = MTYPE_BITMAP; + joystickMenu.back.generic.name = ART_BACK0; + joystickMenu.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + joystickMenu.back.generic.id = ID_BACK; + joystickMenu.back.generic.callback = UI_JoystickMenu_Event; + joystickMenu.back.generic.x = 0; + joystickMenu.back.generic.y = 480-64; + joystickMenu.back.width = 128; + joystickMenu.back.height = 64; + joystickMenu.back.focuspic = ART_BACK1; + + Menu_AddItem( &joystickMenu.menu, &joystickMenu.banner ); + Menu_AddItem( &joystickMenu.menu, &joystickMenu.framel ); + Menu_AddItem( &joystickMenu.menu, &joystickMenu.framer ); + + for (i = 0; i < MAX_JOYSTICKS; i++) { + Menu_AddItem( &joystickMenu.menu, &joystickMenu.joysticks[i] ); + } + + Menu_AddItem( &joystickMenu.menu, &joystickMenu.back ); + + // Store original joystick + if (trap_Cvar_VariableValue("in_joystick") == 0) { + joystick = 0; + } else { + joystick = 1 + (int)trap_Cvar_VariableValue("in_joystickNo"); + } + + if (joystick < 0 || joystick >= joystickMenu.numJoysticks) { + joystick = 0; + } + + joystickMenu.originalJoystick = joystick; + + // Select joystick + joystickMenu.joysticks[joystick].generic.flags &= ~QMF_PULSEIFFOCUS; + joystickMenu.joysticks[joystick].generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); +} + +/* +================= +UI_Joystick_Cache +================= +*/ +void UI_Joystick_Cache( void ) +{ + trap_R_RegisterShaderNoMip( ART_BACK0 ); + trap_R_RegisterShaderNoMip( ART_BACK1 ); + trap_R_RegisterShaderNoMip( ART_FRAMEL ); + trap_R_RegisterShaderNoMip( ART_FRAMER ); +} + +/* +=============== +UI_JoystickMenu +=============== +*/ +void UI_JoystickMenu( void ) { + UI_Joystick_MenuInit(); + UI_PushMenu( &joystickMenu.menu ); +} + Property changes on: code/q3_ui/ui_joystick.c ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + native