Paranoia2/mainui/menu_playersetup.cpp

550 lines
17 KiB
C++

/*
Copyright (C) 1997-2001 Id Software, Inc.
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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mathlib.h"
#include "extdll.h"
#include "const.h"
#include "basemenu.h"
#include "utils.h"
#include "keydefs.h"
#include "ref_params.h"
#include "cl_entity.h"
#include "entity_types.h"
#include "menu_btnsbmp_table.h"
#define ART_BANNER "gfx/shell/head_customize"
#define ID_BACKGROUND 0
#define ID_BANNER 1
#define ID_DONE 2
#define ID_ADVOPTIONS 3
#define ID_VIEW 4
#define ID_NAME 5
#define ID_MODEL 6
#define ID_TOPCOLOR 7
#define ID_BOTTOMCOLOR 8
#define ID_HIMODELS 9
#define ID_SHOWMODELS 10
#define MAX_PLAYERMODELS 100
typedef struct
{
char models[MAX_PLAYERMODELS][CS_SIZE];
int num_models;
char currentModel[CS_SIZE];
ref_viewpass_t rvp;
cl_entity_t *ent;
menuFramework_s menu;
menuBitmap_s background;
menuBitmap_s banner;
menuPicButton_s done;
menuPicButton_s AdvOptions;
menuBitmap_s view;
menuCheckBox_s showModels;
menuCheckBox_s hiModels;
menuSlider_s topColor;
menuSlider_s bottomColor;
menuField_s name;
menuSpinControl_s model;
} uiPlayerSetup_t;
static uiPlayerSetup_t uiPlayerSetup;
static HIMAGE playerImage = 0; // keep actual
static char lastImage[256];
/*
=================
UI_PlayerSetup_CalcFov
assume refdef is valid
=================
*/
static void UI_PlayerSetup_CalcFov( ref_viewpass_t *rvp )
{
rvp->fov_x = 40.0f;
float x = rvp->viewport[2] / tan( DEG2RAD( rvp->fov_x ) * 0.5f );
float half_fov_y = atan( rvp->viewport[3] / x );
rvp->fov_y = RAD2DEG( half_fov_y ) * 2;
}
/*
=================
UI_PlayerSetup_FindModels
=================
*/
static void UI_PlayerSetup_FindModels( void )
{
char name[256], path[256];
char **filenames;
int i, numFiles;
uiPlayerSetup.num_models = 0;
// Get file list
filenames = FS_SEARCH( "models/player/*", &numFiles, TRUE );
if( !numFiles ) filenames = FS_SEARCH( "models/player/*", &numFiles, FALSE );
#if 1
// add default singleplayer model
strcpy( uiPlayerSetup.models[uiPlayerSetup.num_models], "player" );
uiPlayerSetup.num_models++;
#endif
// build the model list
for( i = 0; i < numFiles; i++ )
{
COM_FileBase( filenames[i], name );
sprintf( path, "models/player/%s/%s.mdl", name, name );
if( !FILE_EXISTS( path )) continue;
strcpy( uiPlayerSetup.models[uiPlayerSetup.num_models], name );
uiPlayerSetup.num_models++;
}
}
/*
=================
UI_PlayerSetup_GetConfig
=================
*/
static void UI_PlayerSetup_GetConfig( void )
{
int i;
strncpy( uiPlayerSetup.name.buffer, CVAR_GET_STRING( "name" ), sizeof( uiPlayerSetup.name.buffer ));
// find models
UI_PlayerSetup_FindModels();
// select current model
for( i = 0; i < uiPlayerSetup.num_models; i++ )
{
if( !stricmp( uiPlayerSetup.models[i], CVAR_GET_STRING( "model" )))
{
uiPlayerSetup.model.curValue = (float)i;
break;
}
}
if( gMenu.m_gameinfo.flags & GFL_NOMODELS )
uiPlayerSetup.model.curValue = 0.0f; // force to default
strcpy( uiPlayerSetup.currentModel, uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue] );
uiPlayerSetup.model.maxValue = (float)(uiPlayerSetup.num_models - 1);
uiPlayerSetup.topColor.curValue = CVAR_GET_FLOAT( "topcolor" ) / 255;
uiPlayerSetup.bottomColor.curValue = CVAR_GET_FLOAT( "bottomcolor" ) / 255;
if( CVAR_GET_FLOAT( "cl_himodels" ))
uiPlayerSetup.hiModels.enabled = 1;
if( CVAR_GET_FLOAT( "ui_showmodels" ))
uiPlayerSetup.showModels.enabled = 1;
}
/*
=================
UI_PlayerSetup_SetConfig
=================
*/
static void UI_PlayerSetup_SetConfig( void )
{
CVAR_SET_STRING( "name", uiPlayerSetup.name.buffer );
CVAR_SET_STRING( "model", uiPlayerSetup.currentModel );
CVAR_SET_FLOAT( "topcolor", (int)(uiPlayerSetup.topColor.curValue * 255 ));
CVAR_SET_FLOAT( "bottomcolor", (int)(uiPlayerSetup.bottomColor.curValue * 255 ));
CVAR_SET_FLOAT( "cl_himodels", uiPlayerSetup.hiModels.enabled );
CVAR_SET_FLOAT( "ui_showmodels", uiPlayerSetup.showModels.enabled );
}
/*
=================
UI_PlayerSetup_UpdateConfig
=================
*/
static void UI_PlayerSetup_UpdateConfig( void )
{
char path[256], name[256];
char newImage[256];
int topColor, bottomColor;
// see if the model has changed
if( stricmp( uiPlayerSetup.currentModel, uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue] ))
{
strcpy( uiPlayerSetup.currentModel, uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue] );
}
uiPlayerSetup.model.generic.name = uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue];
strcpy( name, uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue] );
if( !stricmp( name, "player" ))
{
strcpy( path, "models/player.mdl" );
newImage[0] = '\0';
}
else
{
sprintf( path, "models/player/%s/%s.mdl", name, name );
sprintf( newImage, "models/player/%s/%s.bmp", name, name );
}
topColor = (int)(uiPlayerSetup.topColor.curValue * 255 );
bottomColor = (int)(uiPlayerSetup.bottomColor.curValue * 255 );
CVAR_SET_STRING( "model", uiPlayerSetup.currentModel );
CVAR_SET_FLOAT( "cl_himodels", uiPlayerSetup.hiModels.enabled );
CVAR_SET_FLOAT( "ui_showmodels", uiPlayerSetup.showModels.enabled );
CVAR_SET_FLOAT( "topcolor", topColor );
CVAR_SET_FLOAT( "bottomcolor", bottomColor );
// IMPORTANT: always set default model becuase we need to have something valid here
// if you wish draw your playermodel as normal studiomodel please change "models/player.mdl" to path
if( uiPlayerSetup.ent )
ENGINE_SET_MODEL( uiPlayerSetup.ent, "models/player.mdl" );
if( !ui_showmodels->value )
{
if( stricmp( lastImage, newImage ))
{
if( lastImage[0] && playerImage )
{
// release old image
PIC_Free( lastImage );
lastImage[0] = '\0';
playerImage = 0;
}
if( stricmp( name, "player" ))
{
sprintf( lastImage, "models/player/%s/%s.bmp", name, name );
playerImage = PIC_Load( lastImage, PIC_KEEP_SOURCE ); // if present of course
}
else if( lastImage[0] && playerImage )
{
// release old image
PIC_Free( lastImage );
lastImage[0] = '\0';
playerImage = 0;
}
}
if( playerImage != 0 ) // update remap colors
PIC_Remap( playerImage, topColor, bottomColor );
}
}
/*
=================
UI_PlayerSetup_Callback
=================
*/
static void UI_PlayerSetup_Callback( void *self, int event )
{
menuCommon_s *item = (menuCommon_s *)self;
switch( item->id )
{
case ID_HIMODELS:
case ID_SHOWMODELS:
if( event == QM_PRESSED )
((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_PRESSED;
else ((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_FOCUS;
break;
}
if( event == QM_CHANGED )
{
UI_PlayerSetup_UpdateConfig();
return;
}
if( event != QM_ACTIVATED )
return;
switch( item->id )
{
case ID_DONE:
UI_PlayerSetup_SetConfig();
UI_PopMenu();
break;
case ID_ADVOPTIONS:
UI_PlayerSetup_SetConfig();
UI_GameOptions_Menu();
break;
}
}
/*
=================
UI_PlayerSetup_Ownerdraw
=================
*/
static void UI_PlayerSetup_Ownerdraw( void *self )
{
menuCommon_s *item = (menuCommon_s *)self;
// draw the background
UI_FillRect( item->x, item->y, item->width, item->height, uiPromptBgColor );
// draw the rectangle
UI_DrawRectangle( item->x, item->y, item->width, item->height, uiInputFgColor );
if( !ui_showmodels->value && playerImage != 0 )
{
PIC_Set( playerImage, 255, 255, 255, 255 );
PIC_Draw( item->x, item->y, item->width, item->height );
}
else
{
R_ClearScene ();
// clearing body for each frame
uiPlayerSetup.ent->curstate.body = 0;
// draw the player model
R_AddEntity( ET_NORMAL, uiPlayerSetup.ent );
R_RenderFrame( &uiPlayerSetup.rvp );
}
}
/*
=================
UI_PlayerSetup_Init
=================
*/
static void UI_PlayerSetup_Init( void )
{
bool game_hlRally = FALSE;
int addFlags = 0;
memset( &uiPlayerSetup, 0, sizeof( uiPlayerSetup_t ));
// disable playermodel preview for HLRally to prevent crash
if( !stricmp( gMenu.m_gameinfo.gamefolder, "hlrally" ))
game_hlRally = TRUE;
if( gMenu.m_gameinfo.flags & GFL_NOMODELS )
addFlags |= QMF_INACTIVE;
uiPlayerSetup.menu.vidInitFunc = UI_PlayerSetup_Init;
uiPlayerSetup.background.generic.id = ID_BACKGROUND;
uiPlayerSetup.background.generic.type = QMTYPE_BITMAP;
uiPlayerSetup.background.generic.flags = QMF_INACTIVE;
uiPlayerSetup.background.generic.x = 0;
uiPlayerSetup.background.generic.y = 0;
uiPlayerSetup.background.generic.width = 1024;
uiPlayerSetup.background.generic.height = 768;
uiPlayerSetup.background.pic = ART_BACKGROUND;
uiPlayerSetup.banner.generic.id = ID_BANNER;
uiPlayerSetup.banner.generic.type = QMTYPE_BITMAP;
uiPlayerSetup.banner.generic.flags = QMF_INACTIVE|QMF_DRAW_ADDITIVE;
uiPlayerSetup.banner.generic.x = UI_BANNER_POSX;
uiPlayerSetup.banner.generic.y = UI_BANNER_POSY;
uiPlayerSetup.banner.generic.width = UI_BANNER_WIDTH;
uiPlayerSetup.banner.generic.height = UI_BANNER_HEIGHT;
uiPlayerSetup.banner.pic = ART_BANNER;
uiPlayerSetup.done.generic.id = ID_DONE;
uiPlayerSetup.done.generic.type = QMTYPE_BM_BUTTON;
uiPlayerSetup.done.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiPlayerSetup.done.generic.x = 72;
uiPlayerSetup.done.generic.y = 230;
uiPlayerSetup.done.generic.name = "Done";
uiPlayerSetup.done.generic.statusText = "Go back to the Multiplayer Menu";
uiPlayerSetup.done.generic.callback = UI_PlayerSetup_Callback;
UI_UtilSetupPicButton( &uiPlayerSetup.done, PC_DONE );
uiPlayerSetup.AdvOptions.generic.id = ID_ADVOPTIONS;
uiPlayerSetup.AdvOptions.generic.type = QMTYPE_BM_BUTTON;
uiPlayerSetup.AdvOptions.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiPlayerSetup.AdvOptions.generic.x = 72;
uiPlayerSetup.AdvOptions.generic.y = 280;
uiPlayerSetup.AdvOptions.generic.name = "Adv. Options";
uiPlayerSetup.AdvOptions.generic.statusText = "Configure handness, fov and other advanced options";
uiPlayerSetup.AdvOptions.generic.callback = UI_PlayerSetup_Callback;
UI_UtilSetupPicButton( &uiPlayerSetup.AdvOptions, PC_ADV_OPT );
uiPlayerSetup.view.generic.id = ID_VIEW;
uiPlayerSetup.view.generic.type = QMTYPE_BITMAP;
uiPlayerSetup.view.generic.flags = QMF_INACTIVE;
uiPlayerSetup.view.generic.x = 660;
uiPlayerSetup.view.generic.y = 260;
uiPlayerSetup.view.generic.width = 260;
uiPlayerSetup.view.generic.height = 320;
uiPlayerSetup.view.generic.ownerdraw = UI_PlayerSetup_Ownerdraw;
uiPlayerSetup.name.generic.id = ID_NAME;
uiPlayerSetup.name.generic.type = QMTYPE_FIELD;
uiPlayerSetup.name.generic.flags = QMF_CENTER_JUSTIFY|QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiPlayerSetup.name.generic.x = 320;
uiPlayerSetup.name.generic.y = 260;
uiPlayerSetup.name.generic.width = 256;
uiPlayerSetup.name.generic.height = 36;
uiPlayerSetup.name.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.name.generic.statusText = "Enter your multiplayer display name";
uiPlayerSetup.name.maxLength = 32;
uiPlayerSetup.model.generic.id = ID_MODEL;
uiPlayerSetup.model.generic.type = QMTYPE_SPINCONTROL;
uiPlayerSetup.model.generic.flags = QMF_CENTER_JUSTIFY|QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|addFlags;
uiPlayerSetup.model.generic.x = game_hlRally ? 320 : 702;
uiPlayerSetup.model.generic.y = game_hlRally ? 320 : 590;
uiPlayerSetup.model.generic.width = game_hlRally ? 256 : 176;
uiPlayerSetup.model.generic.height = game_hlRally ? 36 : 32;
uiPlayerSetup.model.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.model.generic.statusText = "Select a model for representation in multiplayer";
uiPlayerSetup.model.minValue = 0;
uiPlayerSetup.model.maxValue = 1;
uiPlayerSetup.model.range = 1;
uiPlayerSetup.topColor.generic.id = ID_TOPCOLOR;
uiPlayerSetup.topColor.generic.type = QMTYPE_SLIDER;
uiPlayerSetup.topColor.generic.flags = QMF_PULSEIFFOCUS|QMF_DROPSHADOW|addFlags;
uiPlayerSetup.topColor.generic.name = "Top color";
uiPlayerSetup.topColor.generic.x = 250;
uiPlayerSetup.topColor.generic.y = 550;
uiPlayerSetup.topColor.generic.width = 300;
uiPlayerSetup.topColor.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.topColor.generic.statusText = "Set a player model top color";
uiPlayerSetup.topColor.minValue = 0.0;
uiPlayerSetup.topColor.maxValue = 1.0;
uiPlayerSetup.topColor.range = 0.05f;
uiPlayerSetup.bottomColor.generic.id = ID_BOTTOMCOLOR;
uiPlayerSetup.bottomColor.generic.type = QMTYPE_SLIDER;
uiPlayerSetup.bottomColor.generic.flags = QMF_PULSEIFFOCUS|QMF_DROPSHADOW|addFlags;
uiPlayerSetup.bottomColor.generic.name = "Bottom color";
uiPlayerSetup.bottomColor.generic.x = 250;
uiPlayerSetup.bottomColor.generic.y = 620;
uiPlayerSetup.bottomColor.generic.width = 300;
uiPlayerSetup.bottomColor.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.bottomColor.generic.statusText = "Set a player model bottom color";
uiPlayerSetup.bottomColor.minValue = 0.0;
uiPlayerSetup.bottomColor.maxValue = 1.0;
uiPlayerSetup.bottomColor.range = 0.05f;
uiPlayerSetup.showModels.generic.id = ID_SHOWMODELS;
uiPlayerSetup.showModels.generic.type = QMTYPE_CHECKBOX;
uiPlayerSetup.showModels.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW|addFlags;
uiPlayerSetup.showModels.generic.name = "Show 3D Preview";
uiPlayerSetup.showModels.generic.x = 72;
uiPlayerSetup.showModels.generic.y = 380;
uiPlayerSetup.showModels.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.showModels.generic.statusText = "show 3D player models instead of preview thumbnails";
uiPlayerSetup.hiModels.generic.id = ID_HIMODELS;
uiPlayerSetup.hiModels.generic.type = QMTYPE_CHECKBOX;
uiPlayerSetup.hiModels.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW|addFlags;
uiPlayerSetup.hiModels.generic.name = "High quality models";
uiPlayerSetup.hiModels.generic.x = 72;
uiPlayerSetup.hiModels.generic.y = 430;
uiPlayerSetup.hiModels.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.hiModels.generic.statusText = "show hi-res models in multiplayer";
UI_PlayerSetup_GetConfig();
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.background );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.banner );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.done );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.AdvOptions );
// disable playermodel preview for HLRally to prevent crash
if( game_hlRally == FALSE )
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.view );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.name );
if( !( gMenu.m_gameinfo.flags & GFL_NOMODELS ))
{
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.model );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.topColor );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.bottomColor );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.showModels );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.hiModels );
}
// NOTE: must be called after UI_AddItem whan we sure what UI_ScaleCoords is done
uiPlayerSetup.rvp.viewport[0] = uiPlayerSetup.view.generic.x;
uiPlayerSetup.rvp.viewport[1] = uiPlayerSetup.view.generic.y;
uiPlayerSetup.rvp.viewport[2] = uiPlayerSetup.view.generic.width;
uiPlayerSetup.rvp.viewport[3] = uiPlayerSetup.view.generic.height;
UI_PlayerSetup_CalcFov( &uiPlayerSetup.rvp );
uiPlayerSetup.ent = GET_MENU_EDICT ();
if( !uiPlayerSetup.ent )
return;
// adjust entity params
uiPlayerSetup.ent->curstate.number = 1; // IMPORTANT: always set playerindex to 1
uiPlayerSetup.ent->curstate.animtime = gpGlobals->time; // start animation
uiPlayerSetup.ent->curstate.sequence = 1;
uiPlayerSetup.ent->curstate.scale = 1.0f;
uiPlayerSetup.ent->curstate.frame = 0.0f;
uiPlayerSetup.ent->curstate.framerate = 1.0f;
uiPlayerSetup.ent->curstate.effects |= EF_FULLBRIGHT;
uiPlayerSetup.ent->curstate.controller[0] = 127;
uiPlayerSetup.ent->curstate.controller[1] = 127;
uiPlayerSetup.ent->curstate.controller[2] = 127;
uiPlayerSetup.ent->curstate.controller[3] = 127;
uiPlayerSetup.ent->latched.prevcontroller[0] = 127;
uiPlayerSetup.ent->latched.prevcontroller[1] = 127;
uiPlayerSetup.ent->latched.prevcontroller[2] = 127;
uiPlayerSetup.ent->latched.prevcontroller[3] = 127;
uiPlayerSetup.ent->origin[0] = uiPlayerSetup.ent->curstate.origin[0] = 45.0f / tan( DEG2RAD( uiPlayerSetup.rvp.fov_y / 2.0f ));
uiPlayerSetup.ent->origin[2] = uiPlayerSetup.ent->curstate.origin[2] = 2.0f;
uiPlayerSetup.ent->angles[1] = uiPlayerSetup.ent->curstate.angles[1] = 180.0f;
uiPlayerSetup.ent->player = true; // yes, draw me as playermodel
}
/*
=================
UI_PlayerSetup_Precache
=================
*/
void UI_PlayerSetup_Precache( void )
{
PIC_Load( ART_BACKGROUND );
PIC_Load( ART_BANNER );
}
/*
=================
UI_PlayerSetup_Menu
=================
*/
void UI_PlayerSetup_Menu( void )
{
if ( gMenu.m_gameinfo.gamemode == GAME_SINGLEPLAYER_ONLY )
return;
UI_PlayerSetup_Precache();
UI_PlayerSetup_Init();
UI_PlayerSetup_UpdateConfig();
UI_PushMenu( &uiPlayerSetup.menu );
}