This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/client/cl_gameui.c

1066 lines
22 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
cl_menu.c - menu dlls interaction
Copyright (C) 2010 Uncle Mike
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 3 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.
*/
2010-07-18 22:00:00 +02:00
#include "common.h"
#include "client.h"
#include "const.h"
2010-12-14 22:00:00 +01:00
#include "gl_local.h"
2011-03-08 22:00:00 +01:00
#include "library.h"
2011-04-01 22:00:00 +02:00
#include "input.h"
2010-07-18 22:00:00 +02:00
2011-03-20 22:00:00 +01:00
static MENUAPI GetMenuAPI;
2016-11-17 22:00:00 +01:00
static void UI_UpdateUserinfo( void );
2011-04-08 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
gameui_static_t gameui;
2010-07-18 22:00:00 +02:00
void UI_UpdateMenu( float realtime )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
2017-02-21 22:00:00 +01:00
// menu time (not paused, not clamped)
gameui.globals->time = host.realtime;
gameui.globals->frametime = host.realframetime;
gameui.globals->demoplayback = cls.demoplayback;
gameui.globals->demorecording = cls.demorecording;
2018-03-03 22:00:00 +01:00
gameui.globals->allow_console = host.allow_console;
2017-02-21 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
gameui.dllFuncs.pfnRedraw( realtime );
2011-01-03 22:00:00 +01:00
UI_UpdateUserinfo();
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
void UI_KeyEvent( int key, qboolean down )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnKeyEvent( key, down );
2010-07-18 22:00:00 +02:00
}
void UI_MouseMove( int x, int y )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnMouseMove( x, y );
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
void UI_SetActiveMenu( qboolean fActive )
2010-07-18 22:00:00 +02:00
{
2010-09-30 22:00:00 +02:00
movie_state_t *cin_state;
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance )
2011-03-23 22:00:00 +01:00
{
if( !fActive )
Key_SetKeyDest( key_game );
2010-12-21 22:00:00 +01:00
return;
2011-03-23 22:00:00 +01:00
}
2010-12-21 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
gameui.drawLogo = fActive;
gameui.dllFuncs.pfnSetActiveMenu( fActive );
2010-09-30 22:00:00 +02:00
if( !fActive )
{
// close logo when menu is shutdown
cin_state = AVI_GetState( CIN_LOGO );
AVI_CloseVideo( cin_state );
}
2010-07-18 22:00:00 +02:00
}
void UI_AddServerToList( netadr_t adr, const char *info )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnAddServerToList( adr, info );
2010-07-18 22:00:00 +02:00
}
void UI_GetCursorPos( int *pos_x, int *pos_y )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnGetCursorPos( pos_x, pos_y );
2010-07-18 22:00:00 +02:00
}
void UI_SetCursorPos( int pos_x, int pos_y )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnSetCursorPos( pos_x, pos_y );
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
void UI_ShowCursor( qboolean show )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnShowCursor( show );
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
qboolean UI_CreditsActive( void )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return 0;
return gameui.dllFuncs.pfnCreditsActive();
2010-07-18 22:00:00 +02:00
}
void UI_CharEvent( int key )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnCharEvent( key );
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
qboolean UI_MouseInRect( void )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return 1;
return gameui.dllFuncs.pfnMouseInRect();
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
qboolean UI_IsVisible( void )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return 0;
return gameui.dllFuncs.pfnIsVisible();
2010-07-18 22:00:00 +02:00
}
2010-09-30 22:00:00 +02:00
static void UI_DrawLogo( const char *filename, float x, float y, float width, float height )
{
static float cin_time;
static int last_frame = -1;
2010-10-01 22:00:00 +02:00
byte *cin_data = NULL;
2010-09-30 22:00:00 +02:00
movie_state_t *cin_state;
int cin_frame;
2010-10-26 22:00:00 +02:00
qboolean redraw = false;
2010-09-30 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
if( !gameui.drawLogo ) return;
2010-09-30 22:00:00 +02:00
cin_state = AVI_GetState( CIN_LOGO );
if( !AVI_IsActive( cin_state ))
{
string path;
const char *fullpath;
// run cinematic if not
2011-03-09 22:00:00 +01:00
Q_snprintf( path, sizeof( path ), "media/%s", filename );
2018-02-28 22:00:00 +01:00
COM_DefaultExtension( path, ".avi" );
2011-03-08 22:00:00 +01:00
fullpath = FS_GetDiskPath( path, false );
2010-09-30 22:00:00 +02:00
2011-03-08 22:00:00 +01:00
if( FS_FileExists( path, false ) && !fullpath )
2010-09-30 22:00:00 +02:00
{
2011-04-08 22:00:00 +02:00
MsgDev( D_ERROR, "Couldn't load %s from packfile. Please extract it\n", path );
2016-11-17 22:00:00 +01:00
gameui.drawLogo = false;
2010-09-30 22:00:00 +02:00
return;
}
2017-03-08 22:00:00 +01:00
AVI_OpenVideo( cin_state, fullpath, false, true );
2016-11-17 22:00:00 +01:00
if( !( AVI_GetVideoInfo( cin_state, &gameui.logo_xres, &gameui.logo_yres, &gameui.logo_length )))
2010-09-30 22:00:00 +02:00
{
AVI_CloseVideo( cin_state );
2016-11-17 22:00:00 +01:00
gameui.drawLogo = false;
2010-09-30 22:00:00 +02:00
return;
}
cin_time = 0.0f;
last_frame = -1;
}
2010-10-01 22:00:00 +02:00
if( width <= 0 || height <= 0 )
{
// precache call, don't draw
cin_time = 0.0f;
last_frame = -1;
return;
}
2010-10-09 22:00:00 +02:00
// advances cinematic time (ignores maxfps and host_framerate settings)
cin_time += host.realframetime;
2010-09-30 22:00:00 +02:00
// restarts the cinematic
2016-11-17 22:00:00 +01:00
if( cin_time > gameui.logo_length )
2010-09-30 22:00:00 +02:00
cin_time = 0.0f;
// read the next frame
cin_frame = AVI_GetVideoFrameNumber( cin_state, cin_time );
if( cin_frame != last_frame )
{
2010-10-01 22:00:00 +02:00
cin_data = AVI_GetVideoFrame( cin_state, cin_frame );
2010-09-30 22:00:00 +02:00
last_frame = cin_frame;
redraw = true;
}
2016-11-17 22:00:00 +01:00
R_DrawStretchRaw( x, y, width, height, gameui.logo_xres, gameui.logo_yres, cin_data, redraw );
2010-09-30 22:00:00 +02:00
}
static int UI_GetLogoWidth( void )
{
2016-11-17 22:00:00 +01:00
return gameui.logo_xres;
2010-09-30 22:00:00 +02:00
}
static int UI_GetLogoHeight( void )
{
2016-11-17 22:00:00 +01:00
return gameui.logo_yres;
2010-09-30 22:00:00 +02:00
}
2011-01-03 22:00:00 +01:00
2011-02-05 22:00:00 +01:00
static float UI_GetLogoLength( void )
{
2016-11-17 22:00:00 +01:00
return gameui.logo_length;
2011-02-05 22:00:00 +01:00
}
2011-01-03 22:00:00 +01:00
static void UI_UpdateUserinfo( void )
{
player_info_t *player;
2017-02-12 22:00:00 +01:00
if( !host.userinfo_changed )
return;
2016-11-17 22:00:00 +01:00
player = &gameui.playerinfo;
2011-01-03 22:00:00 +01:00
2017-02-12 22:00:00 +01:00
Q_strncpy( player->userinfo, cls.userinfo, sizeof( player->userinfo ));
2011-03-09 22:00:00 +01:00
Q_strncpy( player->name, Info_ValueForKey( player->userinfo, "name" ), sizeof( player->name ));
Q_strncpy( player->model, Info_ValueForKey( player->userinfo, "model" ), sizeof( player->model ));
2011-07-22 22:00:00 +02:00
player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" ));
player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" ));
2017-02-12 22:00:00 +01:00
host.userinfo_changed = false; // we got it
2011-01-03 22:00:00 +01:00
}
2010-09-30 22:00:00 +02:00
2010-07-18 22:00:00 +02:00
void Host_Credits( void )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
gameui.dllFuncs.pfnFinalCredits();
2010-07-18 22:00:00 +02:00
}
static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
{
2011-03-09 22:00:00 +01:00
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
Q_strncpy( out->title, in->title, sizeof( out->title ));
Q_strncpy( out->version, va( "%g", in->version ), sizeof( out->version ));
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
Q_strncpy( out->size, Q_pretifymem( in->size, 0 ), sizeof( out->size ));
Q_strncpy( out->type, in->type, sizeof( out->type ));
Q_strncpy( out->date, in->date, sizeof( out->date ));
2010-07-18 22:00:00 +02:00
out->gamemode = in->gamemode;
2013-03-01 21:00:00 +01:00
if( in->nomodels )
out->flags |= GFL_NOMODELS;
2010-07-18 22:00:00 +02:00
}
2010-10-26 22:00:00 +02:00
static qboolean PIC_Scissor( float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 )
2010-07-18 22:00:00 +02:00
{
float dudx, dvdy;
// clip sub rect to sprite
if(( width == 0 ) || ( height == 0 ))
return false;
2016-11-17 22:00:00 +01:00
if( *x + *width <= gameui.ds.scissor_x )
2010-07-18 22:00:00 +02:00
return false;
2016-11-17 22:00:00 +01:00
if( *x >= gameui.ds.scissor_x + gameui.ds.scissor_width )
2010-07-18 22:00:00 +02:00
return false;
2016-11-17 22:00:00 +01:00
if( *y + *height <= gameui.ds.scissor_y )
2010-07-18 22:00:00 +02:00
return false;
2016-11-17 22:00:00 +01:00
if( *y >= gameui.ds.scissor_y + gameui.ds.scissor_height )
2010-07-18 22:00:00 +02:00
return false;
dudx = (*u1 - *u0) / *width;
dvdy = (*v1 - *v0) / *height;
2016-11-17 22:00:00 +01:00
if( *x < gameui.ds.scissor_x )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
*u0 += (gameui.ds.scissor_x - *x) * dudx;
*width -= gameui.ds.scissor_x - *x;
*x = gameui.ds.scissor_x;
2010-07-18 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
if( *x + *width > gameui.ds.scissor_x + gameui.ds.scissor_width )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
*u1 -= (*x + *width - (gameui.ds.scissor_x + gameui.ds.scissor_width)) * dudx;
*width = gameui.ds.scissor_x + gameui.ds.scissor_width - *x;
2010-07-18 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
if( *y < gameui.ds.scissor_y )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
*v0 += (gameui.ds.scissor_y - *y) * dvdy;
*height -= gameui.ds.scissor_y - *y;
*y = gameui.ds.scissor_y;
2010-07-18 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
if( *y + *height > gameui.ds.scissor_y + gameui.ds.scissor_height )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
*v1 -= (*y + *height - (gameui.ds.scissor_y + gameui.ds.scissor_height)) * dvdy;
*height = gameui.ds.scissor_y + gameui.ds.scissor_height - *y;
2010-07-18 22:00:00 +02:00
}
return true;
}
/*
====================
PIC_DrawGeneric
draw hudsprite routine
====================
*/
2010-12-02 22:00:00 +01:00
static void PIC_DrawGeneric( float x, float y, float width, float height, const wrect_t *prc )
2010-07-18 22:00:00 +02:00
{
float s1, s2, t1, t2;
2011-03-04 22:00:00 +01:00
int w, h;
2010-07-18 22:00:00 +02:00
2011-03-04 22:00:00 +01:00
// assume we get sizes from image
2016-11-17 22:00:00 +01:00
R_GetTextureParms( &w, &h, gameui.ds.gl_texturenum );
2010-07-18 22:00:00 +02:00
if( prc )
{
2010-07-20 22:00:00 +02:00
// calc user-defined rectangle
2011-03-04 22:00:00 +01:00
s1 = (float)prc->left / (float)w;
t1 = (float)prc->top / (float)h;
s2 = (float)prc->right / (float)w;
t2 = (float)prc->bottom / (float)h;
if( width == -1 && height == -1 )
{
width = prc->right - prc->left;
height = prc->bottom - prc->top;
}
2010-07-18 22:00:00 +02:00
}
else
{
s1 = t1 = 0.0f;
s2 = t2 = 1.0f;
}
2011-03-04 22:00:00 +01:00
if( width == -1 && height == -1 )
{
width = w;
height = h;
}
2010-07-18 22:00:00 +02:00
// pass scissor test if supposed
2016-11-17 22:00:00 +01:00
if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
2010-07-18 22:00:00 +02:00
return;
2011-09-28 22:00:00 +02:00
PicAdjustSize( &x, &y, &width, &height );
2016-11-17 22:00:00 +01:00
R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, gameui.ds.gl_texturenum );
2010-12-14 22:00:00 +01:00
pglColor4ub( 255, 255, 255, 255 );
2010-07-18 22:00:00 +02:00
}
/*
===============================================================================
2010-11-15 22:00:00 +01:00
MainUI Builtin Functions
2010-07-18 22:00:00 +02:00
===============================================================================
*/
/*
=========
pfnPIC_Load
=========
*/
2011-10-09 22:00:00 +02:00
static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long image_size, long flags )
2010-07-18 22:00:00 +02:00
{
2011-03-20 22:00:00 +01:00
HIMAGE tx;
2010-07-18 22:00:00 +02:00
if( !szPicName || !*szPicName )
{
MsgDev( D_ERROR, "CL_LoadImage: bad name!\n" );
return 0;
}
2011-03-20 22:00:00 +01:00
2011-10-09 22:00:00 +02:00
// add default parms to image
2018-03-13 22:00:00 +01:00
SetBits( flags, TF_IMAGE );
2011-10-06 22:00:00 +02:00
2018-03-13 22:00:00 +01:00
Image_SetForceFlags( IL_LOAD_DECAL ); // allow decal images for menu
2012-11-20 21:00:00 +01:00
tx = GL_LoadTexture( szPicName, image_buf, image_size, flags, NULL );
2018-03-13 22:00:00 +01:00
Image_ClearForceFlags();
2011-03-20 22:00:00 +01:00
return tx;
2010-07-18 22:00:00 +02:00
}
/*
=========
2010-12-02 22:00:00 +01:00
pfnPIC_Width
2010-07-18 22:00:00 +02:00
=========
*/
2010-12-02 22:00:00 +01:00
static int pfnPIC_Width( HIMAGE hPic )
2010-07-18 22:00:00 +02:00
{
2010-12-02 22:00:00 +01:00
int picWidth;
2010-07-18 22:00:00 +02:00
2010-12-02 22:00:00 +01:00
R_GetTextureParms( &picWidth, NULL, hPic );
2010-07-18 22:00:00 +02:00
2010-12-02 22:00:00 +01:00
return picWidth;
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_Height
=========
*/
2010-12-02 22:00:00 +01:00
static int pfnPIC_Height( HIMAGE hPic )
2010-07-18 22:00:00 +02:00
{
int picHeight;
2010-12-02 22:00:00 +01:00
R_GetTextureParms( NULL, &picHeight, hPic );
2010-07-18 22:00:00 +02:00
return picHeight;
}
/*
=========
pfnPIC_Set
=========
*/
2010-12-02 22:00:00 +01:00
void pfnPIC_Set( HIMAGE hPic, int r, int g, int b, int a )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
gameui.ds.gl_texturenum = hPic;
2010-12-14 22:00:00 +01:00
r = bound( 0, r, 255 );
g = bound( 0, g, 255 );
b = bound( 0, b, 255 );
a = bound( 0, a, 255 );
pglColor4ub( r, g, b, a );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_Draw
=========
*/
2010-12-02 22:00:00 +01:00
void pfnPIC_Draw( int x, int y, int width, int height, const wrect_t *prc )
2010-07-18 22:00:00 +02:00
{
2013-03-03 21:00:00 +01:00
GL_SetRenderMode( kRenderNormal );
2010-12-02 22:00:00 +01:00
PIC_DrawGeneric( x, y, width, height, prc );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_DrawTrans
=========
*/
2010-12-02 22:00:00 +01:00
void pfnPIC_DrawTrans( int x, int y, int width, int height, const wrect_t *prc )
2010-07-18 22:00:00 +02:00
{
2010-12-02 22:00:00 +01:00
GL_SetRenderMode( kRenderTransTexture );
PIC_DrawGeneric( x, y, width, height, prc );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_DrawHoles
=========
*/
2010-12-02 22:00:00 +01:00
void pfnPIC_DrawHoles( int x, int y, int width, int height, const wrect_t *prc )
2010-07-18 22:00:00 +02:00
{
2010-12-02 22:00:00 +01:00
GL_SetRenderMode( kRenderTransAlpha );
PIC_DrawGeneric( x, y, width, height, prc );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_DrawAdditive
=========
*/
2010-12-02 22:00:00 +01:00
void pfnPIC_DrawAdditive( int x, int y, int width, int height, const wrect_t *prc )
2010-07-18 22:00:00 +02:00
{
2010-12-02 22:00:00 +01:00
GL_SetRenderMode( kRenderTransAdd );
PIC_DrawGeneric( x, y, width, height, prc );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_EnableScissor
=========
*/
static void pfnPIC_EnableScissor( int x, int y, int width, int height )
{
// check bounds
2016-11-17 22:00:00 +01:00
x = bound( 0, x, gameui.globals->scrWidth );
y = bound( 0, y, gameui.globals->scrHeight );
width = bound( 0, width, gameui.globals->scrWidth - x );
height = bound( 0, height, gameui.globals->scrHeight - y );
gameui.ds.scissor_x = x;
gameui.ds.scissor_width = width;
gameui.ds.scissor_y = y;
gameui.ds.scissor_height = height;
gameui.ds.scissor_test = true;
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnPIC_DisableScissor
=========
*/
static void pfnPIC_DisableScissor( void )
{
2016-11-17 22:00:00 +01:00
gameui.ds.scissor_x = 0;
gameui.ds.scissor_width = 0;
gameui.ds.scissor_y = 0;
gameui.ds.scissor_height = 0;
gameui.ds.scissor_test = false;
2010-07-18 22:00:00 +02:00
}
/*
=============
pfnFillRGBA
=============
*/
static void pfnFillRGBA( int x, int y, int width, int height, int r, int g, int b, int a )
{
2010-12-14 22:00:00 +01:00
r = bound( 0, r, 255 );
g = bound( 0, g, 255 );
b = bound( 0, b, 255 );
a = bound( 0, a, 255 );
pglColor4ub( r, g, b, a );
2010-12-02 22:00:00 +01:00
GL_SetRenderMode( kRenderTransTexture );
2017-03-06 22:00:00 +01:00
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, tr.whiteTexture );
2010-12-14 22:00:00 +01:00
pglColor4ub( 255, 255, 255, 255 );
2010-07-18 22:00:00 +02:00
}
/*
=============
pfnClientCmd
=============
*/
2011-04-06 22:00:00 +02:00
static void pfnClientCmd( int exec_now, const char *szCmdString )
2010-07-18 22:00:00 +02:00
{
2011-04-08 22:00:00 +02:00
if( !szCmdString || !szCmdString[0] )
return;
2011-04-06 22:00:00 +02:00
Cbuf_AddText( szCmdString );
2011-04-08 22:00:00 +02:00
Cbuf_AddText( "\n" );
2011-04-06 22:00:00 +02:00
2011-04-08 22:00:00 +02:00
// client command executes immediately
2011-04-06 22:00:00 +02:00
if( exec_now ) Cbuf_Execute();
2010-07-18 22:00:00 +02:00
}
/*
=============
pfnPlaySound
=============
*/
static void pfnPlaySound( const char *szSound )
{
2018-03-20 22:00:00 +01:00
if( !COM_CheckString( szSound )) return;
2014-10-31 22:00:00 +01:00
S_StartLocalSound( szSound, VOL_NORM, false );
2010-07-18 22:00:00 +02:00
}
/*
=============
pfnDrawCharacter
2010-07-20 22:00:00 +02:00
quakefont draw character
2010-07-18 22:00:00 +02:00
=============
*/
2012-06-25 22:00:00 +02:00
static void pfnDrawCharacter( int ix, int iy, int iwidth, int iheight, int ch, int ulRGBA, HIMAGE hFont )
2010-07-18 22:00:00 +02:00
{
2010-07-20 22:00:00 +02:00
rgba_t color;
float row, col, size;
2012-06-25 22:00:00 +02:00
float s1, t1, s2, t2;
float x = ix, y = iy;
float width = iwidth;
float height = iheight;
2010-07-18 22:00:00 +02:00
2010-07-20 22:00:00 +02:00
ch &= 255;
2010-07-18 22:00:00 +02:00
2010-12-02 22:00:00 +01:00
if( ch == ' ' ) return;
2010-07-20 22:00:00 +02:00
if( y < -height ) return;
color[3] = (ulRGBA & 0xFF000000) >> 24;
color[0] = (ulRGBA & 0xFF0000) >> 16;
color[1] = (ulRGBA & 0xFF00) >> 8;
color[2] = (ulRGBA & 0xFF) >> 0;
2010-12-14 22:00:00 +01:00
pglColor4ubv( color );
2010-07-20 22:00:00 +02:00
2012-06-25 22:00:00 +02:00
col = (ch & 15) * 0.0625f + (0.5f / 256.0f);
row = (ch >> 4) * 0.0625f + (0.5f / 256.0f);
2010-07-20 22:00:00 +02:00
size = 0.0625f - (1.0f / 256.0f);
2010-07-18 22:00:00 +02:00
2012-06-25 22:00:00 +02:00
s1 = col;
t1 = row;
s2 = s1 + size;
t2 = t1 + size;
// pass scissor test if supposed
2016-11-17 22:00:00 +01:00
if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
2012-06-25 22:00:00 +02:00
return;
2010-12-02 22:00:00 +01:00
GL_SetRenderMode( kRenderTransTexture );
2012-06-25 22:00:00 +02:00
R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, hFont );
2010-12-14 22:00:00 +01:00
pglColor4ub( 255, 255, 255, 255 );
2010-07-18 22:00:00 +02:00
}
/*
=============
2012-06-25 22:00:00 +02:00
UI_DrawConsoleString
2010-07-18 22:00:00 +02:00
drawing string like a console string
=============
*/
2012-06-25 22:00:00 +02:00
static int UI_DrawConsoleString( int x, int y, const char *string )
2010-07-18 22:00:00 +02:00
{
2010-07-20 22:00:00 +02:00
int drawLen;
2010-07-18 22:00:00 +02:00
if( !string || !*string ) return 0; // silent ignore
2016-11-17 22:00:00 +01:00
drawLen = Con_DrawString( x, y, string, gameui.ds.textColor );
MakeRGBA( gameui.ds.textColor, 255, 255, 255, 255 );
2010-07-20 22:00:00 +02:00
2011-04-08 22:00:00 +02:00
return (x + drawLen); // exclude color prexfixes
2010-07-18 22:00:00 +02:00
}
/*
=============
pfnDrawSetTextColor
set color for anything
=============
*/
2012-06-25 22:00:00 +02:00
static void UI_DrawSetTextColor( int r, int g, int b, int alpha )
2010-07-18 22:00:00 +02:00
{
// bound color and convert to byte
2016-11-17 22:00:00 +01:00
gameui.ds.textColor[0] = r;
gameui.ds.textColor[1] = g;
gameui.ds.textColor[2] = b;
gameui.ds.textColor[3] = alpha;
2010-07-18 22:00:00 +02:00
}
/*
====================
pfnGetPlayerModel
for drawing playermodel previews
====================
*/
2010-08-07 22:00:00 +02:00
static cl_entity_t* pfnGetPlayerModel( void )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
return &gameui.playermodel;
2010-07-18 22:00:00 +02:00
}
/*
====================
pfnSetPlayerModel
for drawing playermodel previews
====================
*/
2010-08-07 22:00:00 +02:00
static void pfnSetPlayerModel( cl_entity_t *ent, const char *path )
2010-07-18 22:00:00 +02:00
{
2018-02-25 22:00:00 +01:00
ent->model = Mod_ForName( path, false, false );
ent->curstate.modelindex = MAX_MODELS; // unreachable index
2010-07-18 22:00:00 +02:00
}
2018-03-20 22:00:00 +01:00
/*
====================
pfnClearScene
for drawing playermodel previews
====================
*/
static void pfnClearScene( void )
{
R_PushScene();
R_ClearScene();
}
2010-07-18 22:00:00 +02:00
/*
====================
pfnRenderScene
for drawing playermodel previews
====================
*/
2017-02-21 22:00:00 +01:00
static void pfnRenderScene( const ref_viewpass_t *rvp )
2010-07-18 22:00:00 +02:00
{
2011-04-08 22:00:00 +02:00
// to avoid division by zero
2017-02-21 22:00:00 +01:00
if( !rvp || rvp->fov_x <= 0.0f || rvp->fov_y <= 0.0f )
2010-12-02 22:00:00 +01:00
return;
2017-02-15 22:00:00 +01:00
2017-02-21 22:00:00 +01:00
// don't allow special modes from menu
((ref_viewpass_t *)&rvp)->flags = 0;
2017-02-15 22:00:00 +01:00
R_Set2DMode( false );
2017-02-21 22:00:00 +01:00
R_RenderFrame( rvp );
2017-02-15 22:00:00 +01:00
R_Set2DMode( true );
2018-03-20 22:00:00 +01:00
R_PopScene();
2010-07-18 22:00:00 +02:00
}
2017-02-21 22:00:00 +01:00
/*
====================
pfnAddEntity
adding player model into visible list
====================
*/
static int pfnAddEntity( int entityType, cl_entity_t *ent )
{
if( !R_AddEntity( ent, entityType ))
return false;
return true;
}
2010-07-18 22:00:00 +02:00
/*
====================
pfnClientJoin
send client connect
====================
*/
static void pfnClientJoin( const netadr_t adr )
{
2011-04-06 22:00:00 +02:00
Cbuf_AddText( va( "connect %s\n", NET_AdrToString( adr )));
2010-07-18 22:00:00 +02:00
}
/*
====================
pfnKeyGetOverstrikeMode
get global key overstrike state
====================
*/
static int pfnKeyGetOverstrikeMode( void )
{
return host.key_overstrike;
}
/*
====================
pfnKeySetOverstrikeMode
set global key overstrike mode
====================
*/
static void pfnKeySetOverstrikeMode( int fActive )
{
host.key_overstrike = fActive;
}
2011-01-09 22:00:00 +01:00
/*
====================
pfnKeyGetState
returns kbutton struct if found
====================
*/
static void *pfnKeyGetState( const char *name )
{
if( clgame.dllFuncs.KB_Find )
return clgame.dllFuncs.KB_Find( name );
return NULL;
}
2010-07-18 22:00:00 +02:00
/*
=========
pfnMemAlloc
=========
*/
static void *pfnMemAlloc( size_t cb, const char *filename, const int fileline )
{
2016-11-17 22:00:00 +01:00
return _Mem_Alloc( gameui.mempool, cb, filename, fileline );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnMemFree
=========
*/
static void pfnMemFree( void *mem, const char *filename, const int fileline )
{
2011-03-11 22:00:00 +01:00
_Mem_Free( mem, filename, fileline );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnGetGameInfo
=========
*/
static int pfnGetGameInfo( GAMEINFO *pgameinfo )
{
if( !pgameinfo ) return 0;
2016-11-17 22:00:00 +01:00
*pgameinfo = gameui.gameInfo;
2010-07-18 22:00:00 +02:00
return 1;
}
/*
=========
pfnGetGamesList
=========
*/
static GAMEINFO **pfnGetGamesList( int *numGames )
{
2011-03-12 22:00:00 +01:00
if( numGames ) *numGames = SI.numgames;
2016-11-17 22:00:00 +01:00
return gameui.modsInfo;
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnGetFilesList
release prev search on a next call
=========
*/
2010-09-10 22:00:00 +02:00
static char **pfnGetFilesList( const char *pattern, int *numFiles, int gamedironly )
2010-07-18 22:00:00 +02:00
{
static search_t *t = NULL;
if( t ) Mem_Free( t ); // release prev search
2011-03-08 22:00:00 +01:00
t = FS_Search( pattern, true, gamedironly );
2010-07-18 22:00:00 +02:00
if( !t )
{
if( numFiles ) *numFiles = 0;
return NULL;
}
if( numFiles ) *numFiles = t->numfilenames;
return t->filenames;
}
/*
=========
pfnGetClipboardData
pointer must be released in call place
=========
*/
static char *pfnGetClipboardData( void )
{
return Sys_GetClipboardData();
}
2010-10-22 22:00:00 +02:00
/*
=========
pfnCheckGameDll
=========
*/
int pfnCheckGameDll( void )
{
void *hInst;
2018-02-27 22:00:00 +01:00
if( SV_Initialized( )) return true;
2010-10-22 22:00:00 +02:00
2018-03-13 22:00:00 +01:00
if(( hInst = COM_LoadLibrary( GI->game_dll, true, false )) != NULL )
2010-10-22 22:00:00 +02:00
{
2018-02-28 22:00:00 +01:00
COM_FreeLibrary( hInst );
2010-10-22 22:00:00 +02:00
return true;
}
return false;
}
2010-07-18 22:00:00 +02:00
/*
=========
pfnChangeInstance
=========
*/
static void pfnChangeInstance( const char *newInstance, const char *szFinalMessage )
{
if( !szFinalMessage ) szFinalMessage = "";
if( !newInstance || !*newInstance ) return;
2011-03-12 22:00:00 +01:00
Host_NewInstance( newInstance, szFinalMessage );
2010-07-18 22:00:00 +02:00
}
/*
=========
pfnHostEndGame
=========
*/
static void pfnHostEndGame( const char *szFinalMessage )
{
if( !szFinalMessage ) szFinalMessage = "";
2018-02-25 22:00:00 +01:00
Host_EndGame( true, szFinalMessage );
2010-07-18 22:00:00 +02:00
}
2012-05-14 22:00:00 +02:00
/*
=========
pfnStartBackgroundTrack
=========
*/
static void pfnStartBackgroundTrack( const char *introTrack, const char *mainTrack )
{
2018-02-15 22:00:00 +01:00
S_StartBackgroundTrack( introTrack, mainTrack, 0, false );
2012-05-14 22:00:00 +02:00
}
2010-07-18 22:00:00 +02:00
// engine callbacks
static ui_enginefuncs_t gEngfuncs =
{
pfnPIC_Load,
2011-04-08 22:00:00 +02:00
GL_FreeImage,
2010-07-18 22:00:00 +02:00
pfnPIC_Width,
2010-12-02 22:00:00 +01:00
pfnPIC_Height,
2010-07-18 22:00:00 +02:00
pfnPIC_Set,
pfnPIC_Draw,
pfnPIC_DrawHoles,
pfnPIC_DrawTrans,
pfnPIC_DrawAdditive,
pfnPIC_EnableScissor,
pfnPIC_DisableScissor,
pfnFillRGBA,
2016-11-17 22:00:00 +01:00
pfnCvar_RegisterGameUIVariable,
2011-04-06 22:00:00 +02:00
Cvar_VariableValue,
Cvar_VariableString,
Cvar_Set,
2017-02-12 22:00:00 +01:00
Cvar_SetValue,
2016-11-17 22:00:00 +01:00
Cmd_AddGameUICommand,
2010-07-18 22:00:00 +02:00
pfnClientCmd,
2011-04-06 22:00:00 +02:00
Cmd_RemoveCommand,
Cmd_Argc,
Cmd_Argv,
Cmd_Args,
2010-08-20 22:00:00 +02:00
Con_Printf,
Con_DPrintf,
2011-04-08 22:00:00 +02:00
UI_NPrintf,
UI_NXPrintf,
2010-07-18 22:00:00 +02:00
pfnPlaySound,
2010-09-30 22:00:00 +02:00
UI_DrawLogo,
UI_GetLogoWidth,
UI_GetLogoHeight,
2011-02-05 22:00:00 +01:00
UI_GetLogoLength,
2010-07-18 22:00:00 +02:00
pfnDrawCharacter,
2012-06-25 22:00:00 +02:00
UI_DrawConsoleString,
UI_DrawSetTextColor,
2010-07-20 22:00:00 +02:00
Con_DrawStringLen,
Con_DefaultColor,
2010-07-18 22:00:00 +02:00
pfnGetPlayerModel,
pfnSetPlayerModel,
2018-03-20 22:00:00 +01:00
pfnClearScene,
2010-07-18 22:00:00 +02:00
pfnRenderScene,
2017-02-21 22:00:00 +01:00
pfnAddEntity,
2010-07-18 22:00:00 +02:00
Host_Error,
2011-04-06 22:00:00 +02:00
FS_FileExists,
2010-07-18 22:00:00 +02:00
pfnGetGameDir,
Cmd_CheckMapsList,
CL_Active,
pfnClientJoin,
2011-04-06 22:00:00 +02:00
COM_LoadFileForMe,
2010-08-20 22:00:00 +02:00
COM_ParseFile,
2011-04-05 22:00:00 +02:00
COM_FreeFile,
2010-07-18 22:00:00 +02:00
Key_ClearStates,
Key_SetKeyDest,
Key_KeynumToString,
Key_GetBinding,
Key_SetBinding,
Key_IsDown,
pfnKeyGetOverstrikeMode,
pfnKeySetOverstrikeMode,
2011-01-09 22:00:00 +01:00
pfnKeyGetState,
2010-07-18 22:00:00 +02:00
pfnMemAlloc,
pfnMemFree,
pfnGetGameInfo,
pfnGetGamesList,
pfnGetFilesList,
2018-03-23 22:00:00 +01:00
SV_GetSaveComment,
CL_GetDemoComment,
2010-10-22 22:00:00 +02:00
pfnCheckGameDll,
2010-07-18 22:00:00 +02:00
pfnGetClipboardData,
2011-04-08 22:00:00 +02:00
Sys_ShellExecute,
2010-07-18 22:00:00 +02:00
Host_WriteServerConfig,
pfnChangeInstance,
2012-05-14 22:00:00 +02:00
pfnStartBackgroundTrack,
2010-07-18 22:00:00 +02:00
pfnHostEndGame,
2017-02-21 22:00:00 +01:00
COM_RandomFloat,
COM_RandomLong,
2011-04-01 22:00:00 +02:00
IN_SetCursor,
pfnIsMapValid,
2011-10-06 22:00:00 +02:00
GL_ProcessTexture,
2011-10-14 22:00:00 +02:00
COM_CompareFileTime,
2017-03-22 22:00:00 +01:00
VID_GetModeString,
2018-04-25 23:00:00 +02:00
COM_SaveFile,
FS_Delete,
2010-07-18 22:00:00 +02:00
};
void UI_UnloadProgs( void )
{
2016-11-17 22:00:00 +01:00
if( !gameui.hInstance ) return;
2010-07-18 22:00:00 +02:00
// deinitialize game
2016-11-17 22:00:00 +01:00
gameui.dllFuncs.pfnShutdown();
2010-07-18 22:00:00 +02:00
2017-02-12 22:00:00 +01:00
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
2016-11-17 22:00:00 +01:00
2018-02-28 22:00:00 +01:00
COM_FreeLibrary( gameui.hInstance );
2016-11-17 22:00:00 +01:00
Mem_FreePool( &gameui.mempool );
memset( &gameui, 0, sizeof( gameui ));
2017-02-12 22:00:00 +01:00
Cvar_Unlink( FCVAR_GAMEUIDLL );
2016-11-17 22:00:00 +01:00
Cmd_Unlink( CMD_GAMEUIDLL );
2010-07-18 22:00:00 +02:00
}
2011-03-20 22:00:00 +01:00
qboolean UI_LoadProgs( void )
2010-07-18 22:00:00 +02:00
{
2011-01-09 22:00:00 +01:00
static ui_enginefuncs_t gpEngfuncs;
2010-07-18 22:00:00 +02:00
static ui_globalvars_t gpGlobals;
int i;
2016-11-17 22:00:00 +01:00
if( gameui.hInstance ) UI_UnloadProgs();
2010-07-18 22:00:00 +02:00
// setup globals
2016-11-17 22:00:00 +01:00
gameui.globals = &gpGlobals;
2010-07-18 22:00:00 +02:00
2018-03-13 22:00:00 +01:00
if(( gameui.hInstance = COM_LoadLibrary( va( "%s/menu.dll", GI->dll_path ), false, false )) == NULL )
2011-08-14 22:00:00 +02:00
{
2018-03-13 22:00:00 +01:00
if(( gameui.hInstance = COM_LoadLibrary( "menu.dll", false, true )) == NULL )
2011-08-14 22:00:00 +02:00
return false;
}
2018-03-13 22:00:00 +01:00
if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL )
2011-08-14 22:00:00 +02:00
{
2018-02-28 22:00:00 +01:00
COM_FreeLibrary( gameui.hInstance );
2011-08-14 22:00:00 +02:00
MsgDev( D_NOTE, "UI_LoadProgs: can't init menu API\n" );
2016-11-17 22:00:00 +01:00
gameui.hInstance = NULL;
2011-08-14 22:00:00 +02:00
return false;
}
2010-07-18 22:00:00 +02:00
2011-01-09 22:00:00 +01:00
// make local copy of engfuncs to prevent overwrite it with user dll
2016-11-17 22:00:00 +01:00
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
2011-01-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
gameui.mempool = Mem_AllocPool( "Menu Pool" );
2011-08-14 22:00:00 +02:00
2016-11-17 22:00:00 +01:00
if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals ))
2010-07-18 22:00:00 +02:00
{
2018-02-28 22:00:00 +01:00
COM_FreeLibrary( gameui.hInstance );
2011-03-20 22:00:00 +01:00
MsgDev( D_NOTE, "UI_LoadProgs: can't init menu API\n" );
2016-11-17 22:00:00 +01:00
Mem_FreePool( &gameui.mempool );
gameui.hInstance = NULL;
2010-07-18 22:00:00 +02:00
return false;
}
2017-02-12 22:00:00 +01:00
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
2016-11-17 22:00:00 +01:00
2010-07-18 22:00:00 +02:00
// setup gameinfo
2011-03-12 22:00:00 +01:00
for( i = 0; i < SI.numgames; i++ )
2010-07-18 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
gameui.modsInfo[i] = Mem_Alloc( gameui.mempool, sizeof( GAMEINFO ));
UI_ConvertGameInfo( gameui.modsInfo[i], SI.games[i] );
2010-07-18 22:00:00 +02:00
}
2016-11-17 22:00:00 +01:00
UI_ConvertGameInfo( &gameui.gameInfo, SI.GameInfo ); // current gameinfo
2010-07-18 22:00:00 +02:00
// setup globals
2018-03-03 22:00:00 +01:00
gameui.globals->allow_console = host.allow_console;
2010-07-18 22:00:00 +02:00
// initialize game
2016-11-17 22:00:00 +01:00
gameui.dllFuncs.pfnInit();
2010-07-18 22:00:00 +02:00
return true;
}