?? menu.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 <ctype.h>
#ifdef _WIN32
#include <io.h>
#endif
#include "client.h"
#include "../client/qmenu.h"
static int m_main_cursor;
#define NUM_CURSOR_FRAMES 15
static char *menu_in_sound = "misc/menu1.wav";
static char *menu_move_sound = "misc/menu2.wav";
static char *menu_out_sound = "misc/menu3.wav";
void M_Menu_Main_f (void);
void M_Menu_Game_f (void);
void M_Menu_LoadGame_f (void);
void M_Menu_SaveGame_f (void);
void M_Menu_PlayerConfig_f (void);
void M_Menu_DownloadOptions_f (void);
void M_Menu_Credits_f( void );
void M_Menu_Multiplayer_f( void );
void M_Menu_JoinServer_f (void);
void M_Menu_AddressBook_f( void );
void M_Menu_StartServer_f (void);
void M_Menu_DMOptions_f (void);
void M_Menu_Video_f (void);
void M_Menu_Options_f (void);
void M_Menu_Keys_f (void);
void M_Menu_Quit_f (void);
void M_Menu_Credits( void );
qboolean m_entersound; // play after drawing a frame, so caching
// won't disrupt the sound
void (*m_drawfunc) (void);
const char *(*m_keyfunc) (int key);
//=============================================================================
/* Support Routines */
#define MAX_MENU_DEPTH 8
typedef struct
{
void (*draw) (void);
const char *(*key) (int k);
} menulayer_t;
menulayer_t m_layers[MAX_MENU_DEPTH];
int m_menudepth;
static void M_Banner( char *name )
{
int w, h;
re.DrawGetPicSize (&w, &h, name );
re.DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name );
}
void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) )
{
int i;
if (Cvar_VariableValue ("maxclients") == 1
&& Com_ServerState ())
Cvar_Set ("paused", "1");
// if this menu is already present, drop back to that level
// to avoid stacking menus by hotkeys
for (i=0 ; i<m_menudepth ; i++)
if (m_layers[i].draw == draw &&
m_layers[i].key == key)
{
m_menudepth = i;
}
if (i == m_menudepth)
{
if (m_menudepth >= MAX_MENU_DEPTH)
Com_Error (ERR_FATAL, "M_PushMenu: MAX_MENU_DEPTH");
m_layers[m_menudepth].draw = m_drawfunc;
m_layers[m_menudepth].key = m_keyfunc;
m_menudepth++;
}
m_drawfunc = draw;
m_keyfunc = key;
m_entersound = true;
cls.key_dest = key_menu;
}
void M_ForceMenuOff (void)
{
m_drawfunc = 0;
m_keyfunc = 0;
cls.key_dest = key_game;
m_menudepth = 0;
Key_ClearStates ();
Cvar_Set ("paused", "0");
}
void M_PopMenu (void)
{
S_StartLocalSound( menu_out_sound );
if (m_menudepth < 1)
Com_Error (ERR_FATAL, "M_PopMenu: depth < 1");
m_menudepth--;
m_drawfunc = m_layers[m_menudepth].draw;
m_keyfunc = m_layers[m_menudepth].key;
if (!m_menudepth)
M_ForceMenuOff ();
}
const char *Default_MenuKey( menuframework_s *m, int key )
{
const char *sound = NULL;
menucommon_s *item;
if ( m )
{
if ( ( item = Menu_ItemAtCursor( m ) ) != 0 )
{
if ( item->type == MTYPE_FIELD )
{
if ( Field_Key( ( menufield_s * ) item, key ) )
return NULL;
}
}
}
switch ( key )
{
case K_ESCAPE:
M_PopMenu();
return menu_out_sound;
case K_KP_UPARROW:
case K_UPARROW:
if ( m )
{
m->cursor--;
Menu_AdjustCursor( m, -1 );
sound = menu_move_sound;
}
break;
case K_TAB:
if ( m )
{
m->cursor++;
Menu_AdjustCursor( m, 1 );
sound = menu_move_sound;
}
break;
case K_KP_DOWNARROW:
case K_DOWNARROW:
if ( m )
{
m->cursor++;
Menu_AdjustCursor( m, 1 );
sound = menu_move_sound;
}
break;
case K_KP_LEFTARROW:
case K_LEFTARROW:
if ( m )
{
Menu_SlideItem( m, -1 );
sound = menu_move_sound;
}
break;
case K_KP_RIGHTARROW:
case K_RIGHTARROW:
if ( m )
{
Menu_SlideItem( m, 1 );
sound = menu_move_sound;
}
break;
case K_MOUSE1:
case K_MOUSE2:
case K_MOUSE3:
case K_JOY1:
case K_JOY2:
case K_JOY3:
case K_JOY4:
case K_AUX1:
case K_AUX2:
case K_AUX3:
case K_AUX4:
case K_AUX5:
case K_AUX6:
case K_AUX7:
case K_AUX8:
case K_AUX9:
case K_AUX10:
case K_AUX11:
case K_AUX12:
case K_AUX13:
case K_AUX14:
case K_AUX15:
case K_AUX16:
case K_AUX17:
case K_AUX18:
case K_AUX19:
case K_AUX20:
case K_AUX21:
case K_AUX22:
case K_AUX23:
case K_AUX24:
case K_AUX25:
case K_AUX26:
case K_AUX27:
case K_AUX28:
case K_AUX29:
case K_AUX30:
case K_AUX31:
case K_AUX32:
case K_KP_ENTER:
case K_ENTER:
if ( m )
Menu_SelectItem( m );
sound = menu_move_sound;
break;
}
return sound;
}
//=============================================================================
/*
================
M_DrawCharacter
Draws one solid graphics character
cx and cy are in 320*240 coordinates, and will be centered on
higher res screens.
================
*/
void M_DrawCharacter (int cx, int cy, int num)
{
re.DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num);
}
void M_Print (int cx, int cy, char *str)
{
while (*str)
{
M_DrawCharacter (cx, cy, (*str)+128);
str++;
cx += 8;
}
}
void M_PrintWhite (int cx, int cy, char *str)
{
while (*str)
{
M_DrawCharacter (cx, cy, *str);
str++;
cx += 8;
}
}
void M_DrawPic (int x, int y, char *pic)
{
re.DrawPic (x + ((viddef.width - 320)>>1), y + ((viddef.height - 240)>>1), pic);
}
/*
=============
M_DrawCursor
Draws an animating cursor with the point at
x,y. The pic will extend to the left of x,
and both above and below y.
=============
*/
void M_DrawCursor( int x, int y, int f )
{
char cursorname[80];
static qboolean cached;
if ( !cached )
{
int i;
for ( i = 0; i < NUM_CURSOR_FRAMES; i++ )
{
Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i );
re.RegisterPic( cursorname );
}
cached = true;
}
Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f );
re.DrawPic( x, y, cursorname );
}
void M_DrawTextBox (int x, int y, int width, int lines)
{
int cx, cy;
int n;
// draw left side
cx = x;
cy = y;
M_DrawCharacter (cx, cy, 1);
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawCharacter (cx, cy, 4);
}
M_DrawCharacter (cx, cy+8, 7);
// draw middle
cx += 8;
while (width > 0)
{
cy = y;
M_DrawCharacter (cx, cy, 2);
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawCharacter (cx, cy, 5);
}
M_DrawCharacter (cx, cy+8, 8);
width -= 1;
cx += 8;
}
// draw right side
cy = y;
M_DrawCharacter (cx, cy, 3);
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawCharacter (cx, cy, 6);
}
M_DrawCharacter (cx, cy+8, 9);
}
/*
=======================================================================
MAIN MENU
=======================================================================
*/
#define MAIN_ITEMS 5
void M_Main_Draw (void)
{
int i;
int w, h;
int ystart;
int xoffset;
int widest = -1;
int totalheight = 0;
char litname[80];
char *names[] =
{
"m_main_game",
"m_main_multiplayer",
"m_main_options",
"m_main_video",
"m_main_quit",
0
};
for ( i = 0; names[i] != 0; i++ )
{
re.DrawGetPicSize( &w, &h, names[i] );
if ( w > widest )
widest = w;
totalheight += ( h + 12 );
}
ystart = ( viddef.height / 2 - 110 );
xoffset = ( viddef.width - widest + 70 ) / 2;
for ( i = 0; names[i] != 0; i++ )
{
if ( i != m_main_cursor )
re.DrawPic( xoffset, ystart + i * 40 + 13, names[i] );
}
strcpy( litname, names[m_main_cursor] );
strcat( litname, "_sel" );
re.DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname );
M_DrawCursor( xoffset - 25, ystart + m_main_cursor * 40 + 11, (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES );
re.DrawGetPicSize( &w, &h, "m_main_plaque" );
re.DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" );
re.DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" );
}
const char *M_Main_Key (int key)
{
const char *sound = menu_move_sound;
switch (key)
{
case K_ESCAPE:
M_PopMenu ();
break;
case K_KP_DOWNARROW:
case K_DOWNARROW:
if (++m_main_cursor >= MAIN_ITEMS)
m_main_cursor = 0;
return sound;
case K_KP_UPARROW:
case K_UPARROW:
if (--m_main_cursor < 0)
m_main_cursor = MAIN_ITEMS - 1;
return sound;
case K_KP_ENTER:
case K_ENTER:
m_entersound = true;
switch (m_main_cursor)
{
case 0:
M_Menu_Game_f ();
break;
case 1:
M_Menu_Multiplayer_f();
break;
case 2:
M_Menu_Options_f ();
break;
case 3:
M_Menu_Video_f ();
break;
case 4:
M_Menu_Quit_f ();
break;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -