rpgxef/code/ui/ui_playermodel.c
Walter Julius Hennecke a39565b783 Integrated RPG-X2 rpgxEF edition into the rpgxEF repo
... not quite content with where the project files lie but it is ok for
now.
... compiling works fine so far (only tested mingw32 right now)
2012-08-04 12:54:37 +02:00

2153 lines
64 KiB
C

// Copyright (C) 1999-2000 Id Software, Inc.
//
//=================================================
//
// TiM: Just a reference for my whacky jargon in here
// Character = the player model as a whole group (ie kulhane )
// Model = the .model file used to build the character ( ie admiral, cadet etc)
// Skin = the skinset field in the .model file, dictating which .skins to use (ie red/teal/gold... )
// ADDENDUM: Skin = the .skinset file linked to the .model file
//
//=================================================
#include "ui_local.h"
#define PIC_ARROW_UP "menu/common/arrow_up_16.tga"
#define PIC_ARROW_DOWN "menu/common/arrow_dn_16.tga"
#define LOW_MEMORY (5 * 1024 * 1024)
#define MAX_PLAYERNAMELENGTH 21
#define MAX_RACES 64
#define MAX_GENDERS 64
static void PlayerModel_BuildList( void );
static void PlayerModel_SetMenuItems( void );
static void PlayerModel_MenuInit(int menuFrom);
//yes... a lot
#define MAX_PLAYERCHARS 256
#define MAX_PLAYERMODELS 64
#define MAX_PLAYERSKINS 32
#define MAX_MENULISTITEMS 12
#define MIN_SCROLLHEIGHT 8
#define MAX_SCROLLRANGE 236
#define MAX_SCROLLTOP 108
#define ID_MENUCHAR0 0
#define ID_MENUCHAR1 1
#define ID_MENUCHAR2 2
#define ID_MENUCHAR3 3
#define ID_MENUCHAR4 4
#define ID_MENUCHAR5 5
#define ID_MENUCHAR6 6
#define ID_MENUCHAR7 7
#define ID_MENUCHAR8 8
#define ID_MENUCHAR9 9
#define ID_MENUCHAR10 10
#define ID_MENUCHAR11 11
#define ID_UPARROW 100
#define ID_DNARROW 101
#define ID_BACK 102
#define ID_MAINMENU 103
#define ID_INGAMEMENU 104
#define ID_APPLY 105
#define ID_MODELSET 106
#define ID_SKINSET 107
#define ID_RACEFILTER 108
#define ID_GENDERFILTER 109
#define ID_SCROLLBAR 110
#define ID_SETTINGS 20
typedef struct
{
int orgChar;
int orgModel;
int orgSkin;
} storedData_t;
typedef struct
{
char charName[36];
int race;
int gender;
int index;
} charData_t;
typedef struct
{
qboolean mouseDown;
qboolean doubleStep;
int yStart;
} scrollData_t;
typedef struct
{
char filterName[32];
int filterIndex;
} filterData_t;
typedef struct
{
menuframework_s menu;
int prevMenu;
menubitmap_s mainmenu;
menubitmap_s back;
menubitmap_s player;
menubitmap_s charMenu[MAX_MENULISTITEMS];
menubitmap_s upArrow;
menubitmap_s dnArrow;
menulist_s charModel;
menulist_s charSkin;
menulist_s raceFilter;
menulist_s genderFilter;
menubitmap_s apply;
menubitmap_s data;
menubitmap_s model;
menuaction_s scrollBar;
qhandle_t corner_ll_4_4;
qhandle_t corner_ll_4_18;
qhandle_t corner_lr_4_18;
qhandle_t corner_lr_18_4;
qhandle_t corner_ur_18_18;
qhandle_t playerIcon;
//menutext_s modelname;
//menutext_s skinname;
//menutext_s skinnameviewed;
menutext_s playername;
playerInfo_t playerinfo;
int numChars;
charData_t charNames[MAX_PLAYERCHARS]/*[128]*/;
char modelNames[MAX_PLAYERMODELS][32];
char skinNames[MAX_PLAYERMODELS][MAX_PLAYERSKINS][32];
//To save loading time, and the fact that loading data from txt files on the fly per spin cycle,
//can sometimes overload EF if the user gets button happy, We'll make it all data is loaded and consolidated on character choosing
//TiM - I think this is wasteful as all heck, but it can't be helped
//The model functions need the data stored as uniform char arrays,
//and the spin controls need them stored as char pointers. O_o
//But not only that, but since these are memory pointers, applying strUpr
//To them destroys the case in the arrays above.
//Hacky this may be, but there's no way around it without some totally Carmack-coding
//Raven had to do this too, so it's an inherent flaw in Q3 coding
char charNamesUpr[MAX_PLAYERCHARS][64];
char modelNamesUpr[MAX_PLAYERMODELS][64];
char skinNamesUpr[MAX_PLAYERMODELS][MAX_PLAYERSKINS][64];
char* modelList[MAX_PLAYERMODELS];
char* skinList[MAX_PLAYERSKINS];
char modelData[64];
char modelName[32];
//char raceNames[MAX_RACES][32];
filterData_t raceList[MAX_RACES];
char* raceNames[MAX_RACES];
int numRaces;
filterData_t genderList[MAX_GENDERS];
char* genderNames[MAX_GENDERS];
int numGenders;
int selectedChar;
int scrollOffset;
storedData_t storedData; //Original Skin Data
scrollData_t scrollData;
} playermodel_t;
static playermodel_t s_playermodel;
static int QDECL FilterList_Compare( const void *ptr1, const void *ptr2 );
static int QDECL CharMediaList_Compare( const void *ptr1, const void *ptr2 );
static void PlayerModel_DrawLoading( void );
/*
=================
PlayerModel_CheckInArray
TiM: When building an array of races etc,
run it through this list to prevent multiple redundancy
Mental Note: Study Pointer Arithmetic more....
=================
*/
static int PlayerModel_CheckInFilter( char* string, filterData_t *filter, int width, int *num ) {
int i=0;
while( filter[i].filterName[0] && i < width ) {
if ( !Q_stricmp( filter[i].filterName, string ) ) {
//Com_Printf( S_COLOR_RED "String %s already in cell %i\n", array[i], i );
return i;
}
i++;
}
if ( !filter[i].filterName[0] && i < width )
{
Q_strncpyz( filter[i].filterName, string, 32 );
filter[i].filterIndex = i;
*num = *num + 1; //aah I see. You can't call *num++ since that increments the address, not the value XD
}
//Com_Printf( S_COLOR_RED "Added %s to cell %i", array[i], i );
return i;
}
//static int PlayerModel_CheckInArray( char* string, void *array, size_t length ) {
// int i=0;
// char *str=NULL;
//
// for (i = 0; i < length; i++ ) {
// str = ((char **)array)[i]; //funky, yet awesome use of the void type lol
//
// Com_Printf( S_COLOR_RED ": %s\n", str );
//
// if ( !str )
// break;
//
// if ( !Q_stricmp( str, string ) ) {
// return i;
// }
// }
//
// if ( i < length )
// {
// Q_strncpyz( ((char **)array)[i], string, length );
// }
//
// return i;
//}
/*
=================
PlayerModel_LoadAvailableModels
TiM: Loads a list of all the .model
files there are in a character's directory.
NB: In Spin Control menu types, the number
of elements is calced on init only. Each
time we refresh this, we'll need to update ourselves.
=================
*/
static int PlayerModel_LoadAvailableModels( void ) {
int i;
int j;
int numFiles;
char fileList[4096]; //Hopefully, this will never be exceeded ROFL
char* filePtr;
int fileLen;
int strLen;
char* temp;
char fileRoute[MAX_QPATH];
if ( s_playermodel.selectedChar == -1 )
return -1;
Com_sprintf( fileRoute, MAX_QPATH,
"models/players_rpgx/%s",
s_playermodel.charNames[s_playermodel.selectedChar].charName );
//Get our num files
memset( &fileList, 0, sizeof ( fileList ) );
numFiles = trap_FS_GetFileList( fileRoute, ".model", fileList, sizeof(fileList) );
if ( numFiles <=0 )
return -1;
//Convert to ptr for easier manip
filePtr = fileList;
memset( &s_playermodel.modelNames, 0, sizeof( s_playermodel.modelNames ) );
memset( &s_playermodel.modelNamesUpr, 0, sizeof( s_playermodel.modelNamesUpr ) );
memset( s_playermodel.modelList, 0, sizeof( s_playermodel.modelList ) );
//iterate thru all the null terminations in this thing
/**
* RPG-X | Phenix | 27/03/2007
* Made for loop in reverse to correctly order the models. (Task#39)
*/
j = 0;
for ( i = 0; j < MAX_PLAYERMODELS && i < numFiles; i++, filePtr += fileLen+1 ) {
fileLen = strlen( filePtr );
if ( !fileLen || !filePtr )
break;
//TiM - this shouldn't be possible
if ( strchr(filePtr,'/') || strchr(filePtr,'\\') )
{
continue;
}
temp = filePtr;
//TiM: Strip extension
strLen = strlen( temp );
if ( strLen > 6 && !Q_stricmp( temp + strLen - 6, ".model" ) ) {
temp[strLen-6] = '\0';
}
Q_strncpyz( s_playermodel.modelNames[j], temp, sizeof ( s_playermodel.modelNames[j] ) );
j++;
}
//sort the models, then feed them to the rest of the variables
qsort( s_playermodel.modelNames, j, sizeof( s_playermodel.modelNames[0] ), CharMediaList_Compare );
for ( i = 0; i < j; i++ )
{
//TiM: A bit of a hacky ovveride here.
//Make it so 'main' is set by default
if ( !Q_stricmp( s_playermodel.modelNames[i], DEFAULT_MODEL ) ) {
s_playermodel.charModel.curvalue = i;
}
Q_strncpyz( s_playermodel.modelNamesUpr[i], s_playermodel.modelNames[i], sizeof( s_playermodel.modelNamesUpr[i] ) );
s_playermodel.modelList[i] = Q_strupr( s_playermodel.modelNamesUpr[i] );
}
return j;
}
/*
================
PlayerModel_LoadAvailableSkins
TiM: Access our selected .model file, get the skin name framework and
fill the skin array with all the skins we found.
Hoi... this could get complicated... O_o
================
*/
static void PlayerModel_LoadAvailableSkins( void ) {
int j=0;
int i=0;
int fileLen;
char fileBuffer[20000];
int numFiles;
char fileListBuffer[10000];
char* filePtr;
fileHandle_t f;
char filePath[MAX_QPATH];
char* token;
char skinSetFrame[MAX_QPATH];
int strLen;
char* star;
int numSkins=0;
int starFlags;
char skins[MAX_PLAYERSKINS][64];
if ( s_playermodel.selectedChar == -1 )
return;
/*memset( s_playermodel.skinNames, 0, sizeof( s_playermodel.skinNames ) );
memset( s_playermodel.skinNamesUpr, 0, sizeof( s_playermodel.skinNamesUpr ) );
*/
//TiM: Ugh, this is the only way to ensure completely flushing out the skins list on each model
for ( i = 0; i < MAX_PLAYERMODELS; i++ )
{
for( j = 0; j < MAX_PLAYERSKINS; j++ )
{
s_playermodel.skinNames[i][j][0] = '\0';
s_playermodel.skinNamesUpr[i][j][0] = '\0';
}
}
for (i = 0; i < MAX_PLAYERSKINS; i++ )
{
s_playermodel.skinList[i] = NULL;
skins[i][0] = '\0';
}
Com_sprintf( filePath, MAX_QPATH, "models/players_rpgx/%s", s_playermodel.charNames[s_playermodel.selectedChar].charName );
//first load the list of .skinset files we have
numFiles = trap_FS_GetFileList( filePath,
".skinset", fileListBuffer, sizeof(fileListBuffer) );
if ( numFiles <= 0 )
{
Com_Printf( S_COLOR_RED "ERROR: No Skinset files found!\n" );
return;
}
filePtr = fileListBuffer;
j=0;
for ( i = 0; i < MAX_PLAYERSKINS && i < numFiles; i++, filePtr += strLen + 1 )
{
strLen = strlen( filePtr );
if ( !strLen )
break;
//TiM - this shouldn't be possible
if ( strchr(filePtr,'/') || strchr(filePtr,'\\') )
{
continue;
}
token = filePtr;
if ( strLen > 8 && !Q_stricmp( token + (strLen - 8), ".skinset" ) )
{
token[strLen - 8] = '\0';
}
Q_strncpyz( skins[j], token, sizeof( skins[j] ) );
//Com_Printf( S_COLOR_RED "%s\n", skins[j] );
j++;
}
//Com_Printf( "Model Break\n", skins[j] );
//Com_Printf( "%s\n", s_playermodel.modelNames[2] );
j = 0;
while ( j < MAX_PLAYERMODELS )
{
if ( !s_playermodel.modelNames[j][0] )
break;
Com_sprintf( filePath, sizeof( filePath ),
"models/players_rpgx/%s/%s.model",
s_playermodel.charNames[s_playermodel.selectedChar].charName,
s_playermodel.modelNames[j] );
//load the .model data into our active buffer
fileLen = trap_FS_FOpenFile( filePath, &f, FS_READ);
if ( fileLen <= 0 ) {
Com_Printf( S_COLOR_RED "File not found: %s\n", filePath );
return;
}
if ( fileLen > 20000 ) {
Com_Printf( S_COLOR_RED "File exceeded maximum size: %s\n", filePath );
return;
}
memset( &fileBuffer, 0, sizeof( fileBuffer ) );
trap_FS_Read( fileBuffer, sizeof( fileBuffer ), f );
trap_FS_FCloseFile( f );
if ( !fileBuffer[0] )
return;
filePtr = fileBuffer;
COM_BeginParseSession();
memset( skinSetFrame, 0, sizeof( skinSetFrame ) );
while ( 1 ) {
token = COM_Parse( &filePtr );
if ( !token || !filePtr )
break;
if ( !Q_stricmp( token, "skinSet" ) ) {
if ( COM_ParseString( &filePtr, &token ) ) {
continue;
}
Q_strncpyz( skinSetFrame, token, sizeof( skinSetFrame ) );
break;
}
}
//set a default one if nothing found
if ( !skinSetFrame[0] )
{
Com_sprintf( skinSetFrame, sizeof( skinSetFrame ), "%s_*", s_playermodel.modelNames[j]);
}
if ( !strchr( skinSetFrame, '*' ) )
{
Com_Printf( S_COLOR_RED "ERROR: No '*' in skinset define for character: %s/%s\n", s_playermodel.charNames[s_playermodel.selectedChar].charName, s_playermodel.modelNames[j] );
continue;
}
//okay... this is tricky.
//basically, we're starting off with a possible
//"main_*, "*_main", or "ma_*_in" set up, where we have to see
//if a file name like "red_main" is valid, and if it is, isolate the "red" from it
star = strstr( skinSetFrame, "*" );
////star is at the end
if ( (int)(star - skinSetFrame) + 1 == (int)strlen(skinSetFrame) )
{
Q_strncpyz( filePath, skinSetFrame, sizeof( filePath ) );
filePath[strlen(filePath)-1] = '\0';
starFlags = 1;
}
//star is at the front
else if ( (int)(star - skinSetFrame) == 0 )
{
star++; //QVMNOTE
Q_strncpyz( filePath, star, sizeof( filePath ) );
starFlags = 2;
}
else
starFlags = 0;
for ( i = 0; i < MAX_PLAYERSKINS; i++ )
{
if ( !skins[i] || !skins[i][0] )
break;
////star is at the end
if ( starFlags == 1 )
{
if ( strstr( skins[i], filePath ) != NULL )
{
Q_strncpyz( s_playermodel.skinNames[j][numSkins], skins[i] + strlen(filePath), sizeof( s_playermodel.skinNames[j][numSkins] ) );
//Q_strncpyz( s_playermodel.skinNamesUpr[j][numSkins], skins[i] + strlen(filePath), sizeof( s_playermodel.skinNamesUpr[j][numSkins] ) );
numSkins++;
}
}
//star is at the front
else if ( starFlags == 2 )
{
if ( (token = strstr( skins[i], filePath ) ) != NULL )
{
Q_strncpyz( s_playermodel.skinNames[j][numSkins], skins[i], (int)(strlen(skins[i]) - strlen(token))+1 );
//Q_strncpyz( s_playermodel.skinNamesUpr[j][numSkins], skins[i], (int)(strlen(skins[i]) - strlen(token))+1 );
numSkins++;
}
}
//else
//TiM | Come back to this later...
//For now, document it as the star must be at the front or back
}
qsort( s_playermodel.skinNames[j], numSkins, sizeof( s_playermodel.skinNames[j][0] ), CharMediaList_Compare );
for ( i = 0; i < numSkins; i++ )
{
Q_strncpyz( s_playermodel.skinNamesUpr[j][i], s_playermodel.skinNames[j][i], sizeof( s_playermodel.skinNamesUpr[j][i] ) );
//Com_Printf( S_COLOR_BLUE "%s\n", s_playermodel.skinNamesUpr[j][i] );
}
numSkins=0;
j++;
}
}
static int QDECL CharMediaList_Compare( const void *ptr1, const void *ptr2 )
{
const char *str1, *str2;
char chr1, chr2;
str1 = (const char *)ptr1;
str2 = (const char *)ptr2;
//Com_Printf( "STR1: %s STR2: %s\n", str1, str2 );
//default data always comes first
//Actually... we came this far, let's just make it all alphabetic
/*if ( !Q_stricmp( str1, DEFAULT_SKIN ) || !Q_stricmp( str1, DEFAULT_MODEL ) )
{
return -1;
}
else if ( !Q_stricmp( str2, DEFAULT_SKIN ) || !Q_stricmp( str2, DEFAULT_MODEL ) )
{
return 1;
}*/
chr1 = *str1;
chr2 = *str2;
//double check they're lower-case. case matters
if ( chr1 >= 'A' && chr1 <= 'Z' ) chr1 += 32;
if ( chr2 >= 'A' && chr2 <= 'Z' ) chr2 += 32;
//cascade the alphabetical list
while( chr1 == chr2 && chr1 && chr2)
{
chr1 = *(str1++);
chr2 = *(str2++);
}
//based off of their ASCII order.
return ((int)chr1 - (int)chr2);
}
static int QDECL FilterList_Compare( const void *ptr1, const void *ptr2 )
{
const char *str1, *str2;
char chr1, chr2;
str1 = ((filterData_t *)ptr1)->filterName;
str2 = ((filterData_t *)ptr2)->filterName;
//hacky override. Make sure 'All' comes first.
if ( !Q_stricmp( str1, "ALL" ) )
return -1;
chr1 = *str1;
chr2 = *str2;
//double check they're lower-case. case matters
if ( chr1 >= 'A' && chr1 <= 'Z' ) chr1 += 32;
if ( chr2 >= 'A' && chr2 <= 'Z' ) chr2 += 32;
//cascade the alphabetical list
while( chr1 == chr2 && chr1 && chr2)
{
if ( *(str1+1) == '\0' || *(str2+1) == '\0' )
break;
chr1 = *(str1++);
chr2 = *(str2++);
}
//based off of their ASCII order.
return ((int)chr1 - (int)chr2);
}
/*
=================
PlayerModel_PopulateSkinsList
=================
*/
static int PlayerModel_PopulateSkinsList ( void ) {
int i;
int j;
if ( !s_playermodel.skinNames[s_playermodel.charModel.curvalue][0][0] ) {
Com_Printf( S_COLOR_RED "ERROR: No valid skins found.\n" );
return -1;
}
//just to ensure complete erasure of previous entries
for( i = 0; i < MAX_PLAYERSKINS; i++ )
s_playermodel.skinList[i] = NULL;
/**
* RPG-X | Phenix | 27/03/2007
* For loop reversed to output list in alphabetical order. (Task #39)
* RPG-X | TiM | 30/4/2007
* Reverted as it was causing an error with skin names not matching
*/
j = 0;
//for ( i = (MAX_PLAYERSKINS - 1); i >= 0; i-- )
for ( i = 0; i < MAX_PLAYERSKINS; i++ )
{
if ( s_playermodel.skinNames[s_playermodel.charModel.curvalue][i][0] ) //!
{
if ( !Q_stricmp( s_playermodel.skinNames[s_playermodel.charModel.curvalue][i], DEFAULT_SKIN ) )
s_playermodel.charSkin.curvalue = j; //j;
s_playermodel.skinList[j] = s_playermodel.skinNamesUpr[s_playermodel.charModel.curvalue][i];
Q_strupr( s_playermodel.skinList[j] );
j++;
}
}
return j;
}
/*
=================
PlayerModel_OffsetCharList
TiM: Called whenever we scroll the model list.
So it'll cycle the value of each one up and down.
The parameter is a pointer so the updated
value will be passed through the scope to the calling
code area. :)
==================
*/
static void PlayerModel_OffsetCharList( int* offset ) {
char* buffer; //intermediate value so performing strupr won't pwn our case sensitive data
int i;
if ( *offset < 0 ) {
*offset = 0;
}
if ( ( s_playermodel.numChars > MAX_MENULISTITEMS) && (*offset > (s_playermodel.numChars - MAX_MENULISTITEMS ) ) ) {
*offset = (s_playermodel.numChars - MAX_MENULISTITEMS );
}
for ( i = 0; i < MAX_MENULISTITEMS; i++ ) {
buffer = s_playermodel.charNamesUpr[i + *offset];
//Q_strncpyz( buffer, s_playermodel.charNames[i + *offset], sizeof ( buffer ) );
//Com_Printf( "Buffer - %s, %s\n", buffer, s_playermodel.charNames[1] );
if ( !buffer[0] ) {
if ( s_playermodel.charMenu[i].generic.flags & ( QMF_INACTIVE | QMF_HIDDEN ) ) {
break;
}
else {
s_playermodel.charMenu[i].generic.flags = ( QMF_INACTIVE | QMF_HIDDEN );
continue;
}
}
s_playermodel.charMenu[i].generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_playermodel.charMenu[i].textPtr = buffer;
Q_strupr( s_playermodel.charMenu[i].textPtr );
}
}
/*
=================
PlayerModel_RebuildCharMenu
TiM: Called when we scroll the races/gender button.
Rebuild the main list based on the new parameters
=================
*/
static void PlayerModel_RebuildCharMenu( void ) {
int i;
qboolean raceValid=qfalse;
qboolean genderValid=qfalse;
s_playermodel.numChars = 0;
memset( &s_playermodel.charNamesUpr, 0, sizeof( s_playermodel.charNamesUpr ) );
i = 0;
while ( i < MAX_PLAYERCHARS ) {
if ( !s_playermodel.charNames[i].charName[0] )
break;
raceValid = s_playermodel.raceFilter.curvalue == 0 ||
( s_playermodel.raceList[s_playermodel.raceFilter.curvalue].filterIndex == s_playermodel.charNames[i].race );
genderValid = s_playermodel.genderFilter.curvalue == 0 ||
( s_playermodel.genderList[s_playermodel.genderFilter.curvalue].filterIndex == s_playermodel.charNames[i].gender );
//Com_Printf( "Char %s valid: %i %i\n", s_playermodel.charNames[i].charName, raceValid, genderValid );
if ( raceValid && genderValid )
{
Q_strncpyz( s_playermodel.charNamesUpr[s_playermodel.numChars], s_playermodel.charNames[i].charName, sizeof( s_playermodel.charNamesUpr[s_playermodel.numChars] ) );
if ( s_playermodel.raceFilter.curvalue == 0 && s_playermodel.genderFilter.curvalue == 0 )
s_playermodel.charNames[s_playermodel.numChars].index = -1;
else
s_playermodel.charNames[s_playermodel.numChars].index = i;
s_playermodel.numChars++;
}
i++;
}
if ( s_playermodel.numChars < MAX_MENULISTITEMS ) {
s_playermodel.upArrow.generic.flags = ( QMF_INACTIVE | QMF_GRAYED );
s_playermodel.dnArrow.generic.flags = ( QMF_INACTIVE | QMF_GRAYED );
}
else
{
s_playermodel.upArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_playermodel.dnArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
s_playermodel.scrollOffset = 0;
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
}
/*
=================
PlayerModel_SpinPlayer
=================
*/
static void PlayerModel_SpinPlayer( void* ptr, int event)
{
if ( event == QM_ACTIVATED )
{
uis.spinView = qtrue;
uis.cursorpx = uis.cursorx;
}
}
/*
=================
PlayerModel_UpdateModel
=================
*/
static void PlayerModel_UpdateModel( void )
{
vec3_t viewangles;
vec3_t moveangles;
memset( &s_playermodel.playerinfo, 0, sizeof(playerInfo_t) );
viewangles[YAW] = uis.lastYaw;
viewangles[PITCH] = 0;
viewangles[ROLL] = 0;
VectorClear( moveangles );
UI_PlayerInfo_SetModel( &s_playermodel.playerinfo, s_playermodel.modelData );
UI_PlayerInfo_SetInfo( &s_playermodel.playerinfo, BOTH_WALK1, BOTH_WALK1, viewangles, moveangles, WP_0, trap_Cvar_VariableValue( "height" ), trap_Cvar_VariableValue( "weight" ), qfalse );
}
/*
=================
PlayerModel_SaveChanges
=================
*/
static void PlayerModel_SaveChanges( void )
{
trap_Cvar_Set( "model", va("%s/%s/%s",
s_playermodel.charNames[s_playermodel.selectedChar].charName,
s_playermodel.modelNames[s_playermodel.charModel.curvalue],
s_playermodel.skinNames[s_playermodel.charModel.curvalue][s_playermodel.charSkin.curvalue] ) );
//Set backup data
s_playermodel.storedData.orgChar = s_playermodel.selectedChar;
s_playermodel.storedData.orgModel = s_playermodel.charModel.curvalue;
s_playermodel.storedData.orgSkin = s_playermodel.charSkin.curvalue;
Q_strncpyz( s_playermodel.modelData, UI_Cvar_VariableString( "model" ), sizeof ( s_playermodel.modelData ) );
PlayerModel_UpdateModel( );
}
/*
==================
PlayerModel_CheckForChange
==================
*/
static void PlayerModel_CheckForChange( void ) {
qboolean enableSaveButton=qfalse;
if ( s_playermodel.storedData.orgChar != s_playermodel.selectedChar )
enableSaveButton = qtrue;
if ( s_playermodel.storedData.orgModel != s_playermodel.charModel.curvalue )
enableSaveButton = qtrue;
if ( s_playermodel.storedData.orgSkin != s_playermodel.charSkin.curvalue )
enableSaveButton = qtrue;
if ( s_playermodel.charSkin.numitems == 0 )
enableSaveButton = qfalse;
if ( s_playermodel.charModel.numitems == 0 )
enableSaveButton = qfalse;
if ( enableSaveButton ) {
s_playermodel.apply.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
else {
s_playermodel.apply.generic.flags = QMF_INACTIVE | QMF_GRAYED;
}
}
/*
=================
PlayerModel_SetupScrollBar
=================
*/
static void PlayerModel_SetupScrollBar( menuaction_s *bar )
{
int height;
//first make sure it's worth enabling this at all
if ( s_playermodel.numChars <= MAX_MENULISTITEMS )
{
bar->generic.flags = QMF_INACTIVE | QMF_HIDDEN;
return;
}
//show the bar
bar->generic.flags &= ~(QMF_INACTIVE | QMF_HIDDEN);
//calculate the necessary height of the bar
//by default, assume 1 pixel per offset
height = ( MAX_SCROLLRANGE) - ( s_playermodel.numChars - MAX_MENULISTITEMS );
//ensure box doesn't get too small
if ( height < MIN_SCROLLHEIGHT )
{
//double the step in that case
//a bit hacky, but no need for 3 since the limit isn't that high
height = ( MAX_SCROLLRANGE ) - ( s_playermodel.numChars * 0.5 - MAX_MENULISTITEMS );
s_playermodel.scrollData.doubleStep = qtrue;
}
else
{
s_playermodel.scrollData.doubleStep = qfalse;
}
//reset to top
bar->generic.y = bar->generic.top = MAX_SCROLLTOP;
bar->height = height;
bar->generic.bottom = bar->generic.y + height;
}
/*
=================
PlayerModel_UpdateScrollBar
=================
*/
static void PlayerModel_UpdateScrollBar( menuaction_s *bar )
{
bar->generic.y = MAX_SCROLLTOP + s_playermodel.scrollOffset*(s_playermodel.scrollData.doubleStep ? 0.5 : 1);
bar->generic.top = bar->generic.y;
bar->generic.bottom = bar->generic.top + bar->height;
}
/*
=================
PlayerModel_MenuEvent
=================
*/
static void PlayerModel_MenuEvent( void* ptr, int event )
{
if (event != QM_ACTIVATED)
return;
switch (((menucommon_s*)ptr)->id)
{
case ID_BACK:
//PlayerModel_SaveChanges();
UI_PopMenu();
break;
case ID_MAINMENU:
//PlayerModel_SaveChanges();
UI_MainMenu();
break;
case ID_INGAMEMENU:
//PlayerModel_SaveChanges();
UI_InGameMenu();
break;
case ID_SETTINGS:
UI_PopMenu();
//PlayerModel_SaveChanges();
UI_PlayerSettingsMenu(s_playermodel.prevMenu);
break;
case ID_DNARROW:
s_playermodel.scrollOffset++;
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
if ( !(s_playermodel.scrollBar.generic.flags & QMF_INACTIVE ) )
PlayerModel_UpdateScrollBar( &s_playermodel.scrollBar );
break;
case ID_UPARROW:
s_playermodel.scrollOffset--;
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
if ( !(s_playermodel.scrollBar.generic.flags & QMF_INACTIVE ) )
PlayerModel_UpdateScrollBar( &s_playermodel.scrollBar );
break;
case ID_MODELSET:
s_playermodel.charSkin.numitems = PlayerModel_PopulateSkinsList();
if ( s_playermodel.charSkin.numitems != -1 )
{
s_playermodel.charSkin.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
else
{
s_playermodel.skinList[0] = "NONE";
s_playermodel.charSkin.generic.flags = QMF_INACTIVE | QMF_GRAYED;
s_playermodel.charSkin.numitems = 0;
}
break;
case ID_APPLY:
PlayerModel_SaveChanges();
break;
case ID_GENDERFILTER:
PlayerModel_RebuildCharMenu();
PlayerModel_SetupScrollBar( &s_playermodel.scrollBar );
break;
case ID_RACEFILTER:
PlayerModel_RebuildCharMenu();
PlayerModel_SetupScrollBar( &s_playermodel.scrollBar );
break;
case ID_MENUCHAR0:
case ID_MENUCHAR1:
case ID_MENUCHAR2:
case ID_MENUCHAR3:
case ID_MENUCHAR4:
case ID_MENUCHAR5:
case ID_MENUCHAR6:
case ID_MENUCHAR7:
case ID_MENUCHAR8:
case ID_MENUCHAR9:
case ID_MENUCHAR10:
case ID_MENUCHAR11:
{
int temp;
int oldChar = s_playermodel.selectedChar;
s_playermodel.selectedChar = ( ((menucommon_s*)ptr)->id - ID_MENUCHAR0 ) + s_playermodel.scrollOffset;
temp = s_playermodel.selectedChar;
if ( s_playermodel.charNames[ s_playermodel.selectedChar ].index >= 0 ) {
s_playermodel.selectedChar = s_playermodel.charNames[ s_playermodel.selectedChar ].index;
}
//Com_Printf( S_COLOR_RED "%i %i\n", s_playermodel.selectedChar, s_playermodel.charNames[ s_playermodel.selectedChar ].index );
//safety net. Without this, if a player held down 'enter', the game would overflow trying to load the same file over and over really fast. bad, really bad lol
if ( oldChar == s_playermodel.selectedChar && s_playermodel.selectedChar != -1 )
break;
//Reset the spin controls to 0.
//Without this, if we load a char with less models+skins than our last one, the game would crash
//since it'd be trying to parse NULL string data
s_playermodel.charModel.curvalue = 0;
s_playermodel.charSkin.curvalue = 0;
s_playermodel.playerIcon = trap_R_RegisterShaderNoMip( va( "models/players_rpgx/%s/model_icon.jpg", s_playermodel.charNames[s_playermodel.selectedChar].charName ) );
Q_strncpyz( s_playermodel.modelName, s_playermodel.charNamesUpr[ temp ], sizeof( s_playermodel.modelName ) );
s_playermodel.charModel.numitems = PlayerModel_LoadAvailableModels();
if ( s_playermodel.charModel.numitems != -1 )
{
s_playermodel.charModel.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
PlayerModel_LoadAvailableSkins();
s_playermodel.charSkin.numitems = PlayerModel_PopulateSkinsList();
if ( s_playermodel.charSkin.numitems != -1 )
{
s_playermodel.charSkin.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
else
{
s_playermodel.skinList[0] = "NONE";
s_playermodel.charSkin.generic.flags = QMF_INACTIVE | QMF_GRAYED;
s_playermodel.charSkin.numitems = 0;
}
}
//reset the spin control
else
{
s_playermodel.modelList[0] = "NONE";
s_playermodel.charModel.generic.flags = QMF_INACTIVE | QMF_GRAYED;
s_playermodel.charModel.numitems = 0;
}
}
break;
}
PlayerModel_CheckForChange();
}
/*
=================
PlayerModel_MenuKey
=================
*/
static sfxHandle_t PlayerModel_MenuKey( int key )
{
switch( key )
{
case K_MOUSE1:
if ( Menu_ItemAtCursor( &s_playermodel.menu ) == &s_playermodel.scrollBar )
{
uis.activemenu->noNewSelecting = qtrue;
s_playermodel.scrollData.mouseDown = qtrue;
s_playermodel.scrollData.yStart = uis.cursory;
}
break;
}
return ( Menu_DefaultKey( &s_playermodel.menu, key ) );
}
/*
=================
PlayerModel_DrawPlayer
=================
*/
static void PlayerModel_DrawPlayer( void *self )
{
menubitmap_s* b;
vec3_t origin = {-40, 2.5, -4 }; //-3.8
b = (menubitmap_s*) self;
if( trap_MemoryRemaining() <= LOW_MEMORY ) {
UI_DrawProportionalString( b->generic.x, b->generic.y + b->height / 2, "LOW MEMORY", UI_LEFT, color_red );
return;
}
UI_DrawPlayer( (float)b->generic.x, (float)b->generic.y, (float)b->width, (float)b->height, origin, &s_playermodel.playerinfo, (int)(uis.realtime/1.5) );
}
/*
=================
PlayerModel_BuildList
Heavily modifed by TiM
All we'll take into account now
is a valid directory name,
and that it contains a .model file
We'll work the rest out later
=================
*/
static int QDECL PlayerListOrder_Compare( const void *ptr1, const void *ptr2 );
static void PlayerModel_BuildList( void )
{
int numdirs;
int numfiles;
char dirlist[8192];
char filelist[128]; //2048
char* dirptr;
int i, j;
int dirlen;
charData_t *tempBuff;
//int offset;
int temp;
s_playermodel.selectedChar = -1;
s_playermodel.numChars = 0;
// iterate directory of all player models
numdirs = trap_FS_GetFileList("models/players_rpgx", "/", dirlist, sizeof(dirlist) );
dirptr = dirlist;
///Com_Printf("%i folders found\n", numdirs );
for (i=0; i<numdirs && s_playermodel.numChars < MAX_PLAYERCHARS; i++,dirptr+=dirlen+1)
{
dirlen = strlen(dirptr);
if ( !dirptr ) {
break;
}
if (dirlen && dirptr[dirlen-1]=='/')
dirptr[dirlen-1]='\0';
//I'm guessing this is for non-PK3'd files
if (!strcmp(dirptr,".") || !strcmp(dirptr,".."))
continue;
// TiM : Check for .model files. That's all we need
numfiles = 0; //Just to be sure
numfiles = trap_FS_GetFileList( va("models/players_rpgx/%s",dirptr), ".model", filelist, 128 );
temp = qfalse;
if ( numfiles > 0 && dirptr[0] )
{
//TiM - Don't do duplicate chars (Since it caches PK3 and non PK3 ones as separate instances )
for ( j = 0; j < s_playermodel.numChars; j++ )
{
tempBuff = &s_playermodel.charNames[j];
if ( !Q_stricmp( tempBuff->charName, dirptr ) ){
temp = qtrue;
break;
}
}
if ( temp )
continue;
tempBuff = &s_playermodel.charNames[s_playermodel.numChars];
Q_strncpyz( tempBuff->charName, dirptr, sizeof( tempBuff[s_playermodel.numChars].charName ) );
tempBuff->index = -1;
//TiM - Load data on the races if at all possible
if ( trap_FS_GetFileList( va("models/players_rpgx/%s",dirptr), "race.cfg", filelist, 128 ) > 0 )
{
fileHandle_t f;
char buffer[1024];
char* filePtr;
int fileLength;
char* token;
char filePath[MAX_QPATH];
Com_sprintf( filePath, sizeof(filePath), "models/players_rpgx/%s/race.cfg", dirptr );
fileLength = trap_FS_FOpenFile( filePath, &f, FS_READ );
//Com_Printf( S_COLOR_RED "File %s loaded.\n", dirptr );
if ( !fileLength ) {
continue;
}
//Com_Printf( S_COLOR_RED "We have length.\n" );
if ( fileLength > sizeof( buffer ) - 1 ) {
continue;
}
//Com_Printf( S_COLOR_RED "Good size.\n" );
memset( &buffer, 0, sizeof( buffer ) );
trap_FS_Read( buffer, fileLength, f );
//Com_Printf( S_COLOR_RED "Loaded data...\n" );
trap_FS_FCloseFile( f );
if ( !buffer[0] ) {
continue;
}
//Format is 'Race Gender'. Race must precede Gender
filePtr = buffer;
COM_BeginParseSession();
token = COM_Parse( &filePtr );
if ( !token )
continue;
//Com_Printf( S_COLOR_RED "Race %s Loaded\n", token );
//tempBuff->race = PlayerModel_CheckInArray( token, s_playermodel.raceNames, MAX_RACES );
//big dirty hack
/*for( k=0; k < MAX_RACES; k++ )
{
if ( !s_playermodel.raceNames[k].raceName[0] )
{
Q_strncpyz( s_playermodel.raceNames[k].raceName, token, sizeof( s_playermodel.raceNames[k].raceName ) );
tempBuff->race = s_playermodel.raceNames[k].raceIndex = k;
s_playermodel.numRaces++;
break;
}
if ( !Q_stricmp( s_playermodel.raceNames[k].raceName, token ) )
{
tempBuff->race = s_playermodel.raceNames[k].raceIndex = k;
break;
}
}*/
tempBuff->race = PlayerModel_CheckInFilter( token, s_playermodel.raceList, MAX_RACES, &s_playermodel.numRaces );
//Com_Printf( S_COLOR_RED "Number of races now: %i\n", s_playermodel.numRaces );
token = COM_Parse( &filePtr );
if ( !token )
continue;
//Com_Printf( S_COLOR_RED "Gender %s loaded\n", token );
//tempBuff->gender = PlayerModel_CheckInArray( token, s_playermodel.genderNames, MAX_GENDERS );
tempBuff->gender = PlayerModel_CheckInFilter( token, s_playermodel.genderList, MAX_GENDERS, &s_playermodel.numGenders );
//Com_Printf( S_COLOR_RED "%i\n", tempBuff[i].gender );
}
s_playermodel.numChars++;
tempBuff = &s_playermodel.charNames[ s_playermodel.numChars ];
}
}
//TiM - Flip the array so it's the right order
/*
* RPG-X | Phenix | 27/03/2007
* Removed code for Task#39 (List was fliped to be Z-A!!!!)*/
//for ( i = 0; i < s_playermodel.numChars; i++ ) {
// offset = ( ( s_playermodel.numChars - i ) - 1);
// Q_strncpyz( s_playermodel.charNames[i].charName,
// tempBuff[offset].charName,
// sizeof( s_playermodel.charNames[i].charName ) );
// s_playermodel.charNames[i].race = tempBuff[offset].race;
// s_playermodel.charNames[i].gender = tempBuff[offset].gender;
// s_playermodel.charNames[i].index = tempBuff[offset].index;
// Q_strncpyz( s_playermodel.charNamesUpr[i], s_playermodel.charNames[i].charName, sizeof( s_playermodel.charNamesUpr[i] ) );
//}
//RPG-X | TiM | 30-4-2007
//This loop obviously isn't working well enough.
//Bringing out the big guns. Using the Windows/Q3
//Binary data sorting function, qsort.
//sorting function located below
qsort( s_playermodel.charNames, s_playermodel.numChars, sizeof( charData_t ), PlayerListOrder_Compare );
//copy to the upper case list for rendering to the menu
for ( i = 0; i < s_playermodel.numChars; i++ )
Q_strncpyz( s_playermodel.charNamesUpr[i], s_playermodel.charNames[i].charName, sizeof( s_playermodel.charNamesUpr[i] ) );
}
/*
=================
PlayerListOrder_Compare
TiM - 30-4-2007
Called in the above
qsort function.
Re-orders the player
list based on alphabetical
name.
=================
*/
static int QDECL PlayerListOrder_Compare( const void *ptr1, const void *ptr2 )
{
char *chr1, *chr2;
int delta;
//extract the first characters of the name from each entry
chr1 = ((charData_t *)ptr1)->charName;
chr2 = ((charData_t *)ptr2)->charName;
//double check they're lower-case. case matters
if ( *chr1 >= 'A' && *chr1 <= 'Z' ) *chr1 += 32;
if ( *chr2 >= 'A' && *chr2 <= 'Z' ) *chr2 += 32;
//based off of their ASCII order.
delta = (int)*chr1 - (int)*chr2;
//if characters weren't the same
if ( delta != 0 )
return delta;
//else loop through the rest
while ( chr1 && chr2 && delta == 0 )
{
delta = (int)*chr1 - (int)*chr2;
chr1++;
chr2++;
}
return delta;
}
/*
=================
PlayerModel_SetMenuItems
=================
*/
static void PlayerModel_SetMenuItems( void )
{
int i;
char* temp;
//char model[64];
char model[32];
char skin[32];
// name
trap_Cvar_VariableStringBuffer( "name", s_playermodel.playername.string, MAX_PLAYERNAMELENGTH );
// model
trap_Cvar_VariableStringBuffer( "model", s_playermodel.modelData, 64 );
if ( ( temp = strchr( s_playermodel.modelData, '/' ) ) == NULL )
{
Q_strncpyz( s_playermodel.modelName, s_playermodel.modelData, sizeof( s_playermodel.modelName ) );
Q_strncpyz( model, DEFAULT_MODEL, 32 );
Q_strncpyz( skin, DEFAULT_SKIN, 32);
}
else
{
int len;
char* tempSkin;
//
len = strlen( temp );
Q_strncpyz( s_playermodel.modelName, s_playermodel.modelData, (strlen(s_playermodel.modelData) - strlen(temp)) + 1 );
//*temp++;
temp++;
if ( ( tempSkin = strchr( temp, '/' ) ) == NULL ) {
if ( !temp || !temp[1] )
Q_strncpyz( model, DEFAULT_MODEL, 32 );
else
Q_strncpyz( model, temp, 32 );
Q_strncpyz( skin, DEFAULT_SKIN, 32 );
}
else {
len = strlen( tempSkin );
//*tempSkin++;
tempSkin++;
Q_strncpyz( model, temp, (strlen( temp ) - len) + 1 );
if ( !tempSkin || !tempSkin[1] )
Q_strncpyz( skin, DEFAULT_SKIN, 32 );
else
Q_strncpyz( skin, tempSkin, 32 );
}
}
//Com_Printf( S_COLOR_RED "Load model is %s %s %s\n", s_playermodel.modelName, model, skin );
// find model in our list
for (i=0; i<s_playermodel.numChars; i++)
{
if ( !Q_stricmp( s_playermodel.modelName, s_playermodel.charNames[i].charName ) ) {
s_playermodel.selectedChar = i;
break;
}
}
//try to register the current shader icon
if ( s_playermodel.selectedChar != -1 ) {
s_playermodel.playerIcon = trap_R_RegisterShaderNoMip( va( "models/players_rpgx/%s/model_icon", s_playermodel.modelName ) );
//If we're exceeded the list, update it so we're at the top
if ( s_playermodel.selectedChar > MAX_MENULISTITEMS ) {
s_playermodel.scrollOffset = (s_playermodel.selectedChar - MAX_MENULISTITEMS)+1;
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
}
s_playermodel.charModel.numitems = PlayerModel_LoadAvailableModels( );
if ( s_playermodel.charModel.numitems != -1 )
{
s_playermodel.charModel.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
else
{
s_playermodel.charModel.numitems = 0;
s_playermodel.charModel.generic.flags = QMF_GRAYED | QMF_INACTIVE;
s_playermodel.modelList[0] = "NONE";
}
//TiM - Switch the spin controls to the right value;
for ( i=0; i < s_playermodel.charModel.numitems; i++ ) {
if ( !Q_stricmp( s_playermodel.modelList[i], model ) ) {
s_playermodel.charModel.curvalue = i;
break;
}
}
PlayerModel_LoadAvailableSkins( );
s_playermodel.charSkin.numitems = PlayerModel_PopulateSkinsList();
if ( s_playermodel.charSkin.numitems != -1 )
{
s_playermodel.charSkin.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
else
{
s_playermodel.charSkin.numitems = 0;
s_playermodel.charSkin.generic.flags = QMF_GRAYED | QMF_INACTIVE;
s_playermodel.skinList[0] = "NONE";
}
}
for ( i=0; i < s_playermodel.charSkin.numitems; i++ ) {
if ( !Q_stricmp( s_playermodel.skinList[i], skin ) ) {
s_playermodel.charSkin.curvalue = i;
break;
}
}
//Set backup data
s_playermodel.storedData.orgChar = s_playermodel.selectedChar;
s_playermodel.storedData.orgModel = s_playermodel.charModel.curvalue;
s_playermodel.storedData.orgSkin = s_playermodel.charSkin.curvalue;
}
/*
=================
PlayerModel_DrawScrollBar
=================
*/
static void PlayerModel_DrawScrollBar( void *self )
{
qboolean focus;
menuaction_s *bar;
int *y;
int color;
int newY;
int dif;
bar = (menuaction_s *)self;
focus = ( Menu_ItemAtCursor( bar->generic.parent ) == bar );
if ( focus )
color = bar->color2;
else
color = bar->color;
trap_R_SetColor( colorTable[ color ] );
UI_DrawHandlePic( bar->generic.x, bar->generic.y, bar->width, bar->height, uis.whiteShader);
trap_R_SetColor( NULL );
if ( !s_playermodel.scrollData.mouseDown )
return;
if ( !trap_Key_IsDown( K_MOUSE1 ) )
{
s_playermodel.scrollData.mouseDown = qfalse;
uis.activemenu->noNewSelecting = qfalse;
return;
}
if ( uis.cursory == s_playermodel.scrollData.yStart )
return;
y = &bar->generic.y;
newY = *y + (uis.cursory - s_playermodel.scrollData.yStart);
if ( newY+bar->height > MAX_SCROLLTOP + MAX_SCROLLRANGE )
newY = (MAX_SCROLLTOP + MAX_SCROLLRANGE) - bar->height;
if ( newY < MAX_SCROLLTOP )
newY = MAX_SCROLLTOP;
dif = newY - *y;
s_playermodel.scrollOffset += dif * (s_playermodel.scrollData.doubleStep ? 2 : 1);
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
*y = newY;
bar->generic.top = *y;
bar->generic.bottom = *y + bar->height;
s_playermodel.scrollData.yStart = uis.cursory;
}
/*
=================
PlayerSettingsMenu_Graphics
=================
*/
void PlayerModelMenu_Graphics (void)
{
int i;
// Draw the basic screen layout
UI_MenuFrame2(&s_playermodel.menu);
trap_R_SetColor( colorTable[CT_LTBROWN1]);
UI_DrawHandlePic(30,203, 47, 186, uis.whiteShader); // Middle left line
trap_R_SetColor( colorTable[CT_LTORANGE]);
//TiM - Frame around the models selection list
UI_DrawHandlePic( 96, 50, 8, -32, s_playermodel.corner_ll_4_18); // UL Corner
UI_DrawHandlePic( 96, 369, 8, 8, s_playermodel.corner_ll_4_4); // LL Corner
UI_DrawHandlePic( 238, 62, 32, 32, s_playermodel.corner_ur_18_18); // UR Corner
UI_DrawHandlePic( 240, 368, 32, 8, s_playermodel.corner_lr_18_4); // LR Corner
UI_DrawHandlePic( 96, 81, 4, 290, uis.whiteShader); // Left side
UI_DrawHandlePic( 242, 87, 18, 18, uis.whiteShader ); //Right Side Up Arrow Button
if ( s_playermodel.scrollBar.generic.flags & QMF_HIDDEN )
{
UI_DrawHandlePic( 242, 108, 18, 236, uis.whiteShader); // Right side
}
else
{
if ( s_playermodel.scrollBar.generic.y > MAX_SCROLLTOP + 4 )
UI_DrawHandlePic( 242, 108, 18, s_playermodel.scrollBar.generic.y - 108 - 3, uis.whiteShader);
if ( s_playermodel.scrollBar.generic.bottom + 3 < 343 )
UI_DrawHandlePic( 242, s_playermodel.scrollBar.generic.bottom + 3, 18, 343 - 3 - s_playermodel.scrollBar.generic.bottom, uis.whiteShader);
}
UI_DrawHandlePic( 242, 347, 18, 18, uis.whiteShader ); //Right Side Down Button
UI_DrawHandlePic( 100, 62, 141, 18, uis.whiteShader); // Top
UI_DrawHandlePic( 101, 371, 140, 4, uis.whiteShader); // Bottom
//TiM - Frame around the model specific data window
UI_DrawHandlePic( 265, 50, 8, -32, s_playermodel.corner_ll_4_18); // UL Corner
UI_DrawHandlePic( 265, 369, 8, 8, s_playermodel.corner_ll_4_4); // LL Corner
UI_DrawHandlePic( 422, 50, -8, -32, s_playermodel.corner_ll_4_18); // UR Corner
UI_DrawHandlePic( 422, 369, -8, 8, s_playermodel.corner_ll_4_4); // LR Corner
UI_DrawHandlePic( 265, 81, 4, 290, uis.whiteShader); // Left side
UI_DrawHandlePic( 426, 81, 4, 290, uis.whiteShader); // Right side
UI_DrawHandlePic( 269, 62, 157, 18, uis.whiteShader); // Top
UI_DrawHandlePic( 269, 371, 157, 4, uis.whiteShader); // Bottom
//TiM - Draw the stunningly awesome icon of the character
UI_DrawHandlePic( 306, 114, 82, 82, uis.whiteShader);
if ( !s_playermodel.playerIcon ) {
trap_R_SetColor( colorTable[CT_BLACK] );
UI_DrawHandlePic( 307, 115, 80, 80, uis.whiteShader );
UI_DrawProportionalString( 347, 145, "?", UI_BIGFONT|UI_CENTER, colorTable[CT_LTORANGE] );
}
else {
trap_R_SetColor( colorTable[CT_WHITE]);
UI_DrawHandlePic( 307, 115, 80, 80, s_playermodel.playerIcon );
}
//UI_DrawProportionalString( 220, 362, va("%s %d %s %d",menu_normal_text[MNT_SCREEN],(s_playermodel.modelpage + 1),menu_normal_text[MNT_OF],s_playermodel.numpages),UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 108, 64, menu_normal_text[MNT_CHARS],UI_SMALLFONT,colorTable[CT_BLACK]); // Top
UI_DrawProportionalString( 275, 64, menu_normal_text[MNT_CHARDATA], UI_SMALLFONT, colorTable[CT_BLACK] );
trap_R_SetColor( colorTable[CT_DKGREY2]);
UI_DrawHandlePic( 439, 79, 151, 295, uis.whiteShader); // Background
// Frame around player model
trap_R_SetColor( colorTable[CT_LTORANGE]);
UI_DrawHandlePic( 435, 50, 8, -32, s_playermodel.corner_ll_4_18); // UL Corner
UI_DrawHandlePic( 435, 369, 8, 8, s_playermodel.corner_ll_4_4); // LL Corner
UI_DrawHandlePic( 440, 62, 150, 18, uis.whiteShader); // Top
UI_DrawHandlePic( 435, 79, 4, 295, uis.whiteShader); // Left side
UI_DrawHandlePic( 440, 371, 150, 4, uis.whiteShader); // Bottom
// Left rounded ends for buttons
trap_R_SetColor( colorTable[s_playermodel.mainmenu.color]);
UI_DrawHandlePic(s_playermodel.mainmenu.generic.x - 14, s_playermodel.mainmenu.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
trap_R_SetColor( colorTable[s_playermodel.back.color]);
UI_DrawHandlePic(s_playermodel.back.generic.x - 14, s_playermodel.back.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
trap_R_SetColor( colorTable[s_playermodel.data.color]);
UI_DrawHandlePic(s_playermodel.data.generic.x - 14, s_playermodel.data.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
trap_R_SetColor( colorTable[s_playermodel.model.color]);
UI_DrawHandlePic(s_playermodel.model.generic.x - 14, s_playermodel.model.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
//Model Name along the top
if ( s_playermodel.modelName[0] )
{
char* buf = s_playermodel.modelName;
UI_DrawProportionalString( 347, 89, Q_strupr( buf ), UI_SMALLFONT|UI_CENTER,colorTable[CT_DKPURPLE1]);
}
UI_DrawProportionalString( 74, 28, "881",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 150, "2445",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 206, "600",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 395, "3-44",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
//paint the selected model white
{
for ( i = 0; i < MAX_MENULISTITEMS; i++ )
{
if ( s_playermodel.charMenu[i].textcolor == CT_WHITE && s_playermodel.charMenu[i].textcolor2 == CT_WHITE )
{
s_playermodel.charMenu[i].textcolor = CT_DKGOLD1;
s_playermodel.charMenu[i].textcolor2 = CT_LTGOLD1;
}
//override between straight list, and filters
if ( ( s_playermodel.charNames[i + s_playermodel.scrollOffset].index == -1 && i + s_playermodel.scrollOffset == s_playermodel.selectedChar)
||
( s_playermodel.charNames[i + s_playermodel.scrollOffset].index >= 0 && s_playermodel.charNames[i + s_playermodel.scrollOffset].index == s_playermodel.selectedChar )
)
{
//Com_Printf( S_COLOR_GREEN "%i %i %i\n", i, s_playermodel.selectedChar, s_playermodel.charNames[i + s_playermodel.scrollOffset].index );
s_playermodel.charMenu[i].textcolor = CT_WHITE;
s_playermodel.charMenu[i].textcolor2 = CT_WHITE;
}
}
}
}
/*
=================
PlayerSettings_MenuDraw
=================
*/
static void PlayerModel_MenuDraw (void)
{
PlayerModelMenu_Graphics();
Menu_Draw( &s_playermodel.menu );
}
/*
=================
PlayerModel_MenuInit
=================
*/
static void PlayerModel_MenuInit(int menuFrom)
{
int i;
//int j;
//int k;
int x;
int y;
static char playername[32];
//static char modelname[32];
//static char skinname[32];
//static char skinnameviewed[32];
qboolean races=qfalse;
qboolean genders=qfalse;
// zero set all our globals
memset( &s_playermodel, 0 ,sizeof(playermodel_t) );
s_playermodel.prevMenu = menuFrom;
//TiM : Model Spin view
uis.spinView = qfalse;
uis.lastYaw = 150;
PlayerModel_Cache();
//Set up some false data to feed our spin controls for the time being
//Spin controls NEED data passed to them on init, eitherwise they immediately terminate. which sucks lol
s_playermodel.modelList[0] = "NONE";
s_playermodel.skinList[0] = "NONE";
Q_strncpyz( s_playermodel.genderList[0].filterName , "All", 32 );
Q_strncpyz( s_playermodel.raceList[0].filterName, "All", 32 );
// set initial states
PlayerModel_BuildList();
//sort the race list alphabetically
//+1 for number to account for the 'All' value
qsort( (void *)s_playermodel.raceList, s_playermodel.numRaces+1, sizeof( filterData_t ), FilterList_Compare );
qsort( (void *)s_playermodel.genderList, s_playermodel.numGenders+1, sizeof( filterData_t ), FilterList_Compare );
//Populate the spin control pointers
for ( i = 0; i < 128; i++ ) {
if ( !s_playermodel.genderList[i].filterName[0] && !s_playermodel.raceList[i].filterName[0] )
break;
if ( s_playermodel.genderList[i].filterName[0] ) {
s_playermodel.genderNames[i] = s_playermodel.genderList[i].filterName;
genders = qtrue;
}
if ( s_playermodel.raceList[i].filterName[0] ) {
s_playermodel.raceNames[i] = s_playermodel.raceList[i].filterName;
races = qtrue;
}
}
s_playermodel.menu.key = PlayerModel_MenuKey;
s_playermodel.menu.wrapAround = qtrue;
s_playermodel.menu.fullscreen = qtrue;
s_playermodel.menu.draw = PlayerModel_MenuDraw;
s_playermodel.menu.descX = MENU_DESC_X;
s_playermodel.menu.descY = MENU_DESC_Y;
s_playermodel.menu.titleX = MENU_TITLE_X;
s_playermodel.menu.titleY = MENU_TITLE_Y;
s_playermodel.menu.titleI = MNT_CHANGEPLAYER_TITLE;
s_playermodel.menu.footNoteEnum = MNT_CHANGEPLAYER;
s_playermodel.mainmenu.generic.type = MTYPE_BITMAP;
s_playermodel.mainmenu.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_playermodel.mainmenu.generic.x = 110;
s_playermodel.mainmenu.generic.y = 391;
s_playermodel.mainmenu.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_playermodel.mainmenu.generic.callback = PlayerModel_MenuEvent;
s_playermodel.mainmenu.width = MENU_BUTTON_MED_WIDTH;
s_playermodel.mainmenu.height = MENU_BUTTON_MED_HEIGHT;
s_playermodel.mainmenu.color = CT_DKPURPLE1;
s_playermodel.mainmenu.color2 = CT_LTPURPLE1;
if (!ingameFlag)
{
s_playermodel.mainmenu.textEnum = MBT_MAINMENU;
s_playermodel.mainmenu.generic.id = ID_MAINMENU;
}
else
{
s_playermodel.mainmenu.textEnum = MBT_INGAMEMENU;
s_playermodel.mainmenu.generic.id = ID_INGAMEMENU;
}
s_playermodel.mainmenu.textX = MENU_BUTTON_TEXT_X;
s_playermodel.mainmenu.textY = MENU_BUTTON_TEXT_Y;
s_playermodel.mainmenu.textcolor = CT_BLACK;
s_playermodel.mainmenu.textcolor2 = CT_WHITE;
s_playermodel.back.generic.type = MTYPE_BITMAP;
s_playermodel.back.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_playermodel.back.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_playermodel.back.generic.callback = PlayerModel_MenuEvent;
s_playermodel.back.generic.id = ID_BACK;
s_playermodel.back.generic.x = 110;
s_playermodel.back.generic.y = 415;
s_playermodel.back.width = MENU_BUTTON_MED_WIDTH;
s_playermodel.back.height = MENU_BUTTON_MED_HEIGHT;
s_playermodel.back.color = CT_DKPURPLE1;
s_playermodel.back.color2 = CT_LTPURPLE1;
s_playermodel.back.textX = MENU_BUTTON_TEXT_X;
s_playermodel.back.textY = MENU_BUTTON_TEXT_Y;
s_playermodel.back.textEnum = MBT_BACK;
s_playermodel.back.generic.id = ID_BACK;
s_playermodel.back.textcolor = CT_BLACK;
s_playermodel.back.textcolor2 = CT_WHITE;
s_playermodel.data.generic.type = MTYPE_BITMAP;
s_playermodel.data.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_playermodel.data.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_playermodel.data.generic.id = ID_SETTINGS;
s_playermodel.data.generic.callback = PlayerModel_MenuEvent;
s_playermodel.data.generic.x = 482;
s_playermodel.data.generic.y = 391;
s_playermodel.data.width = MENU_BUTTON_MED_WIDTH;
s_playermodel.data.height = MENU_BUTTON_MED_HEIGHT;
s_playermodel.data.color = CT_DKPURPLE1;
s_playermodel.data.color2 = CT_LTPURPLE1;
s_playermodel.data.textX = 5;
s_playermodel.data.textY = 2;
s_playermodel.data.textEnum = MBT_PLAYERDATA;
s_playermodel.data.textcolor = CT_BLACK;
s_playermodel.data.textcolor2 = CT_WHITE;
s_playermodel.model.generic.type = MTYPE_BITMAP;
s_playermodel.model.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_playermodel.model.generic.flags = QMF_GRAYED;
s_playermodel.model.generic.x = 482;
s_playermodel.model.generic.y = 415;
s_playermodel.model.width = MENU_BUTTON_MED_WIDTH;
s_playermodel.model.height = MENU_BUTTON_MED_HEIGHT;
s_playermodel.model.color = CT_DKPURPLE1;
s_playermodel.model.color2 = CT_LTPURPLE1;
s_playermodel.model.textX = 5;
s_playermodel.model.textY = 2;
s_playermodel.model.textEnum = MBT_CHANGEMODEL;
s_playermodel.model.textcolor = CT_BLACK;
s_playermodel.model.textcolor2 = CT_WHITE;
//y = 88;
x = 107;
y = 85;
for (i=0; i < MAX_MENULISTITEMS; i++ ) {
s_playermodel.charMenu[i].generic.type = MTYPE_BITMAP;
s_playermodel.charMenu[i].generic.flags = QMF_INACTIVE | QMF_HIDDEN;
s_playermodel.charMenu[i].generic.x = x;
s_playermodel.charMenu[i].generic.y = y;
s_playermodel.charMenu[i].generic.callback = PlayerModel_MenuEvent;
s_playermodel.charMenu[i].generic.id = ID_MENUCHAR0+i;
s_playermodel.charMenu[i].width = 129;
s_playermodel.charMenu[i].height = 16;
s_playermodel.charMenu[i].color = CT_DKPURPLE1;
s_playermodel.charMenu[i].color2 = CT_LTPURPLE1;
s_playermodel.charMenu[i].textPtr = NULL;
s_playermodel.charMenu[i].textX = 4;
s_playermodel.charMenu[i].textY = 1;
s_playermodel.charMenu[i].textcolor = CT_DKGOLD1;
s_playermodel.charMenu[i].textcolor2 = CT_LTGOLD1;
s_playermodel.charMenu[i].textStyle = UI_SMALLFONT;
y += 24;
}
s_playermodel.playername.generic.type = MTYPE_PTEXT;
s_playermodel.playername.generic.flags = QMF_INACTIVE;
s_playermodel.playername.generic.x = 444;
s_playermodel.playername.generic.y = 63;
s_playermodel.playername.string = playername;
s_playermodel.playername.style = UI_SMALLFONT;
s_playermodel.playername.color = colorTable[CT_BLACK];
/*s_playermodel.modelname.generic.type = MTYPE_PTEXT;
s_playermodel.modelname.generic.flags = QMF_INACTIVE;
s_playermodel.modelname.generic.x = 121;
s_playermodel.modelname.generic.y = 338;
s_playermodel.modelname.string = modelname;
s_playermodel.modelname.style = UI_LEFT;
s_playermodel.modelname.color = colorTable[CT_LTBLUE1];*/
/*s_playermodel.skinname.generic.type = MTYPE_PTEXT;
s_playermodel.skinname.generic.flags = QMF_INACTIVE;
s_playermodel.skinname.generic.x = 323;
s_playermodel.skinname.generic.y = 338;
s_playermodel.skinname.string = skinname;
s_playermodel.skinname.style = UI_RIGHT;
s_playermodel.skinname.color = colorTable[CT_LTBLUE1];*/
s_playermodel.player.generic.type = MTYPE_BITMAP;
s_playermodel.player.generic.flags = QMF_SILENT;
s_playermodel.player.generic.ownerdraw = PlayerModel_DrawPlayer;
s_playermodel.player.generic.callback = PlayerModel_SpinPlayer;
s_playermodel.player.generic.x = 439; //400
s_playermodel.player.generic.y = 80; //20
s_playermodel.player.width = 151; //32*7.3
s_playermodel.player.height = 291; //56*7.3
s_playermodel.upArrow.generic.type = MTYPE_BITMAP;
s_playermodel.upArrow.generic.name = PIC_ARROW_UP;
s_playermodel.upArrow.generic.flags = QMF_GRAYED | QMF_INACTIVE;
s_playermodel.upArrow.generic.callback = PlayerModel_MenuEvent;
s_playermodel.upArrow.generic.id = ID_UPARROW;
s_playermodel.upArrow.generic.x = 243;
s_playermodel.upArrow.generic.y = 89;
s_playermodel.upArrow.width = 16;
s_playermodel.upArrow.height = 16;
s_playermodel.upArrow.color = CT_DKPURPLE1;
s_playermodel.upArrow.color2 = CT_LTPURPLE1;
s_playermodel.upArrow.textX = MENU_BUTTON_TEXT_X;
s_playermodel.upArrow.textY = MENU_BUTTON_TEXT_Y;
//s_playermodel.upArrow.textEnum = MBT_PREVPAGE;
s_playermodel.upArrow.textcolor = CT_BLACK;
s_playermodel.upArrow.textcolor2 = CT_WHITE;
s_playermodel.dnArrow.generic.type = MTYPE_BITMAP;
s_playermodel.dnArrow.generic.name = PIC_ARROW_DOWN;
s_playermodel.dnArrow.generic.flags = QMF_GRAYED | QMF_INACTIVE;
s_playermodel.dnArrow.generic.callback = PlayerModel_MenuEvent;
s_playermodel.dnArrow.generic.id = ID_DNARROW;
s_playermodel.dnArrow.generic.x = 243;
s_playermodel.dnArrow.generic.y = 349;
s_playermodel.dnArrow.width = 16;
s_playermodel.dnArrow.height = 16;
s_playermodel.dnArrow.color = CT_DKPURPLE1;
s_playermodel.dnArrow.color2 = CT_LTPURPLE1;
s_playermodel.dnArrow.textX = MENU_BUTTON_TEXT_X;
s_playermodel.dnArrow.textY = MENU_BUTTON_TEXT_Y;
//s_playermodel.dnArrow.textEnum = MBT_NEXTPAGE;
s_playermodel.dnArrow.textcolor = CT_BLACK;
s_playermodel.dnArrow.textcolor2 = CT_WHITE;
s_playermodel.charModel.generic.type = MTYPE_SPINCONTROL;
s_playermodel.charModel.generic.flags = QMF_INACTIVE | QMF_GRAYED; //QMF_HIGHLIGHT_IF_FOCUS
s_playermodel.charModel.generic.id = ID_MODELSET;
s_playermodel.charModel.generic.callback = PlayerModel_MenuEvent;
s_playermodel.charModel.generic.x = 291;//134;
s_playermodel.charModel.generic.y = 209;//207;
s_playermodel.charModel.textEnum = MBT_CHARMODEL;
s_playermodel.charModel.textcolor = CT_BLACK;
s_playermodel.charModel.textcolor2 = CT_WHITE;
s_playermodel.charModel.color = CT_DKPURPLE1;
s_playermodel.charModel.color2 = CT_LTPURPLE1;
s_playermodel.charModel.width = 92;//80;
s_playermodel.charModel.textX = 56;
s_playermodel.charModel.textY = 2;
s_playermodel.charModel.textFlags = UI_CENTER;
s_playermodel.charModel.listX = 56;
s_playermodel.charModel.listY = 24;
s_playermodel.charModel.listFlags = UI_CENTER;
s_playermodel.charModel.focusWidth = 110;
s_playermodel.charModel.focusHeight = 40;
s_playermodel.charModel.itemnames = (const char **)s_playermodel.modelList;
s_playermodel.charSkin.generic.type = MTYPE_SPINCONTROL;
s_playermodel.charSkin.generic.flags = QMF_INACTIVE | QMF_GRAYED;
s_playermodel.charSkin.generic.id = ID_SKINSET;
s_playermodel.charSkin.generic.callback = PlayerModel_MenuEvent;
s_playermodel.charSkin.generic.x = 291;//134;
s_playermodel.charSkin.generic.y = 266;//207;
s_playermodel.charSkin.textEnum = MBT_CHARSKIN;
s_playermodel.charSkin.textcolor = CT_BLACK;
s_playermodel.charSkin.textcolor2 = CT_WHITE;
s_playermodel.charSkin.color = CT_DKPURPLE1;
s_playermodel.charSkin.color2 = CT_LTPURPLE1;
s_playermodel.charSkin.width = 90;//80;
s_playermodel.charSkin.textX = 56;
s_playermodel.charSkin.textY = 2;
s_playermodel.charSkin.textFlags = UI_CENTER;
s_playermodel.charSkin.listX = 56;
s_playermodel.charSkin.listY = 24;
s_playermodel.charSkin.listFlags = UI_CENTER;
s_playermodel.charSkin.focusWidth = 110;
s_playermodel.charSkin.focusHeight = 40;
s_playermodel.charSkin.itemnames = (const char**)s_playermodel.skinList;
s_playermodel.raceFilter.generic.type = MTYPE_SPINCONTROL;
if ( !races ) {
s_playermodel.raceFilter.generic.flags = QMF_INACTIVE | QMF_GRAYED;
}
else {
s_playermodel.raceFilter.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
s_playermodel.raceFilter.generic.id = ID_RACEFILTER;
s_playermodel.raceFilter.generic.callback = PlayerModel_MenuEvent;
s_playermodel.raceFilter.generic.x = 270;
s_playermodel.raceFilter.generic.y = 391;
s_playermodel.raceFilter.textEnum = MBT_RACEFILTER;
s_playermodel.raceFilter.textcolor = CT_BLACK;
s_playermodel.raceFilter.textcolor2 = CT_WHITE;
s_playermodel.raceFilter.color = CT_DKPURPLE1;
s_playermodel.raceFilter.color2 = CT_LTPURPLE1;
s_playermodel.raceFilter.textX = 10;
s_playermodel.raceFilter.textY = 1;
s_playermodel.raceFilter.width = 65;
s_playermodel.raceFilter.itemnames = (const char**)s_playermodel.raceNames;
s_playermodel.genderFilter.generic.type = MTYPE_SPINCONTROL;
if ( !genders ) {
s_playermodel.genderFilter.generic.flags = QMF_INACTIVE | QMF_GRAYED;
}
else {
s_playermodel.genderFilter.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
s_playermodel.genderFilter.generic.id = ID_GENDERFILTER;
s_playermodel.genderFilter.generic.callback = PlayerModel_MenuEvent;
s_playermodel.genderFilter.generic.x = 270;
s_playermodel.genderFilter.generic.y = 414;
s_playermodel.genderFilter.textEnum = MBT_GENDERFILTER;
s_playermodel.genderFilter.textcolor = CT_BLACK;
s_playermodel.genderFilter.textcolor2 = CT_WHITE;
s_playermodel.genderFilter.color = CT_DKPURPLE1;
s_playermodel.genderFilter.color2 = CT_LTPURPLE1;
s_playermodel.genderFilter.textX = 10;
s_playermodel.genderFilter.textY = 1;
s_playermodel.genderFilter.width = 65;
s_playermodel.genderFilter.itemnames = (const char**)s_playermodel.genderNames;
s_playermodel.apply.generic.type = MTYPE_BITMAP;
s_playermodel.apply.generic.name = GRAPHIC_SQUARE;
s_playermodel.apply.generic.flags = QMF_GRAYED | QMF_INACTIVE;
s_playermodel.apply.generic.callback = PlayerModel_MenuEvent;
s_playermodel.apply.generic.id = ID_APPLY;
s_playermodel.apply.generic.x = 281;
s_playermodel.apply.generic.y = 321;
s_playermodel.apply.width = 132;
s_playermodel.apply.height = 39;
s_playermodel.apply.color = CT_DKPURPLE1;
s_playermodel.apply.color2 = CT_LTPURPLE1;
s_playermodel.apply.textX = MENU_BUTTON_TEXT_X;
s_playermodel.apply.textY = MENU_BUTTON_TEXT_Y;
s_playermodel.apply.textEnum = MBT_VIDEOAPPLYCHANGES;
s_playermodel.apply.textcolor = CT_BLACK;
s_playermodel.apply.textcolor2 = CT_WHITE;
s_playermodel.scrollBar.generic.type = MTYPE_ACTION;
s_playermodel.scrollBar.generic.flags = QMF_INACTIVE | QMF_HIDDEN;
s_playermodel.scrollBar.generic.x = 242;
s_playermodel.scrollBar.generic.y = 108;
s_playermodel.scrollBar.generic.id = ID_SCROLLBAR;
s_playermodel.scrollBar.generic.ownerdraw = PlayerModel_DrawScrollBar;
s_playermodel.scrollBar.width = 18;
s_playermodel.scrollBar.height = MIN_SCROLLHEIGHT;
s_playermodel.scrollBar.color = CT_DKPURPLE1;
s_playermodel.scrollBar.color2 = CT_LTPURPLE1;
Menu_AddItem( &s_playermodel.menu, &s_playermodel.model );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.data );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.player );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.playername );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.upArrow );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.scrollBar );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.dnArrow );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.charModel );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.charSkin );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.apply );
for (i=0; i < MAX_MENULISTITEMS; i++ ) {
Menu_AddItem( &s_playermodel.menu, &s_playermodel.charMenu[i] );
}
Menu_AddItem( &s_playermodel.menu, &s_playermodel.raceFilter );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.genderFilter );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.back );
Menu_AddItem( &s_playermodel.menu, &s_playermodel.mainmenu );
if ( s_playermodel.numChars >= MAX_MENULISTITEMS ) {
s_playermodel.upArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_playermodel.dnArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
}
PlayerModel_SetMenuItems();
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
PlayerModel_SetupScrollBar( &s_playermodel.scrollBar );
PlayerModel_UpdateScrollBar( &s_playermodel.scrollBar );
// update user interface
PlayerModel_UpdateModel();
}
/*
=================
PlayerModel_Cache
=================
*/
void PlayerModel_Cache( void )
{
//int i;
s_playermodel.corner_ll_4_18 = trap_R_RegisterShaderNoMip("menu/common/corner_ll_4_18");
s_playermodel.corner_ll_4_4 = trap_R_RegisterShaderNoMip("menu/common/corner_ll_4_4");
s_playermodel.corner_lr_4_18 = trap_R_RegisterShaderNoMip("menu/common/corner_lr_4_18");
s_playermodel.corner_lr_18_4 = trap_R_RegisterShaderNoMip("menu/common/corner_lr_18_4");
s_playermodel.corner_ur_18_18 = trap_R_RegisterShaderNoMip("menu/common/corner_ur_18_18");
trap_R_RegisterShaderNoMip(PIC_ARROW_UP);
trap_R_RegisterShaderNoMip(PIC_ARROW_DOWN);
}
/*
=================
PlayerModel_DrawLoading
=================
*/
static void PlayerModel_DrawLoading( void )
{
//register the corners now
qhandle_t cornerPic = trap_R_RegisterShaderNoMip("menu/common/corner_ll_47_18.tga");
int y = 50;
trap_R_SetColor( colorTable[CT_DKPURPLE2]);
UI_DrawHandlePic( 132, y+ 42, 128, -64, cornerPic); // Top Left corner
UI_DrawHandlePic( 132, y+252, 128, 64, cornerPic); // Bottom Left corner
UI_DrawHandlePic( 429, y+ 42, -128, -64, cornerPic); // Top Right corner
UI_DrawHandlePic( 429, y+252, -128, 64, cornerPic); // Bottom Right corner
UI_DrawHandlePic(145, y+75, 395, 18, uis.whiteShader); // Top
UI_DrawHandlePic(132, y+93, 47, 175, uis.whiteShader); // Left side
UI_DrawHandlePic(510, y+93, 47, 175, uis.whiteShader); // Right side
UI_DrawHandlePic(147,y+265, 65, 18, uis.whiteShader); // Bottom Left
UI_DrawHandlePic(477,y+265, 65, 18, uis.whiteShader); // Bottom Right
UI_DrawHandlePic(214,y+265, 261, 18, uis.whiteShader); // Bottom
UI_DrawProportionalString(345,y+159,menu_normal_text[MNT_LOADING],UI_SMALLFONT | UI_CENTER,colorTable[CT_LTGOLD1]);
}
/*
=================
PlayerModel_Cache
=================
*/
void UI_PlayerModelMenu(int menuFrom)
{
//TiM - Spawn a quick "loading" box
//Sometimes this gives me the eerie creeps the game froze
PlayerModel_DrawLoading();
PlayerModel_MenuInit(menuFrom);
UI_PushMenu( &s_playermodel.menu );
//Menu_SetCursorToItem( &s_playermodel.menu, &s_playermodel.pics[s_playermodel.selectedmodel % MAX_MODELSPERPAGE] );
}