/* 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. */ // menu_main.c -- the main menu #include #ifdef _WIN32 #include #endif #include "client.h" #include "../client/qmenu.h" static char *menu_in_sound = "misc/menu1.wav"; static char *menu_move_sound = "misc/menu2.wav"; static char *menu_out_sound = "misc/menu3.wav"; static char *creditsBuffer; static int m_main_cursor; #define NUM_CURSOR_FRAMES 15 qboolean m_entersound; // play after drawing a frame, so caching // won't disrupt the sound cvar_t *options_menu; extern cvar_t *alt_text_color; 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; // Knghtmare- added Psychospaz's menu scaling stuff float scaledVideo (float param) { return param*menuScale.avg; } float videoScale (void) { return menuScale.avg; } // end Knightmare // From Q2max void addPlayerButton (buttonmenuobject_t *thisObj, int index, float x, float y, float w, float h) { thisObj->min[0] = x; thisObj->max[0] = x + w; thisObj->min[1] = y; thisObj->max[1] = y + h; thisObj->index = index; } void ActionStartMod (char *mod) { //killserver, start mod, unbind keys, exec configs, and start demos Cbuf_AddText ("killserver\n"); Cbuf_AddText (va("game %s\n", mod)); Cbuf_AddText ("unbindall\n"); Cbuf_AddText ("exec default.cfg\n"); Cbuf_AddText ("exec kmq2config.cfg\n"); Cbuf_AddText ("exec autoexec.cfg\n"); Cbuf_AddText ("d1\n"); } void M_Banner( char *name ) { //float ratio; int w, h; R_DrawGetPicSize (&w, &h, name ); /*if (w) { ratio = 45.0/(float)h; h = 45; w *= ratio; }*/ R_DrawStretchPic ( viddef.width / 2 - scaledVideo(w)/2, viddef.height/ 2 - scaledVideo(150), scaledVideo(w), scaledVideo(h), name, 1.0); //R_DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name ); } // Knightmare- added Psychospaz's mouse support void refreshCursorButtons(void) { cursor.buttonused[MOUSEBUTTON2] = true; cursor.buttonclicks[MOUSEBUTTON2] = 0; cursor.buttonused[MOUSEBUTTON1] = true; cursor.buttonclicks[MOUSEBUTTON1] = 0; } void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) ) { int i; if (Cvar_VariableValue ("maxclients") == 1 && Com_ServerState () && !cls.consoleActive) // Knightmare added Cvar_Set ("paused", "1"); // Knightmare- if just opened menu, and ingame and not DM, grab screen first if (cls.key_dest != key_menu && !Cvar_VariableValue("deathmatch") && Com_ServerState() == 2) //ss_game //&& !cl.cinematictime && Com_ServerState()) R_GrabScreen(); // if this menu is already present, drop back to that level // to avoid stacking menus by hotkeys for (i=0 ; i= 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; // Knightmare- added Psychospaz's mouse support refreshCursorLink(); refreshCursorButtons(); cls.key_dest = key_menu; } void M_ForceMenuOff (void) { // Knightmare- added Psychospaz's mouse support refreshCursorLink(); m_drawfunc = 0; m_keyfunc = 0; cls.key_dest = key_game; m_menudepth = 0; Key_ClearStates (); if (!cls.consoleActive) // Knightmare added 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; // Knightmare- added Psychospaz's mouse support refreshCursorLink(); refreshCursorButtons(); if (!m_menudepth) M_ForceMenuOff (); } void M_BackMenu (void *unused) { M_PopMenu(); } void Options_MenuDraw (void); 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: if (m_drawfunc==Options_MenuDraw && options_menu->value>0) { refreshCursorLink(); Cvar_SetValue( "options_menu", 0 ); } else M_PopMenu(); return menu_out_sound; case K_KP_UPARROW: case K_UPARROW: if ( m ) { m->cursor--; // Knightmare- added Psychospaz's mouse support refreshCursorLink(); Menu_AdjustCursor( m, -1 ); sound = menu_move_sound; } break; case K_TAB: case K_KP_DOWNARROW: case K_DOWNARROW: if ( m ) { m->cursor++; // Knightmare- added Psychospaz's mouse support refreshCursorLink(); 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: //Knightmare 12/22/2001 case K_MOUSE4: case K_MOUSE5:*/ //end Knightmare 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, int red, int green, int blue, int alpha, qboolean italic) { if (videoScale() > 1) R_DrawScaledChar ( scaledVideo( cx + ((MENU_STATIC_WIDTH-320)/2) ), scaledVideo( cy + ((MENU_STATIC_HEIGHT- 240)/2) ), num, videoScale(), red, green, blue, alpha, italic); else R_DrawScaledChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1 ), num, videoScale(), red, green, blue, alpha, italic); //R_DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num, 255); } void M_Print (int cx, int cy, char *str) { int red=0, green=255, blue=0; TextColor ((int)alt_text_color->value, &red, &green, &blue); //DrawAltString (cx, cy, str, 255); while (*str) { M_DrawCharacter (cx, cy, (*str)+128, red,green,blue,255, false); str++; cx += MENU_FONT_SIZE; } } void M_PrintWhite (int cx, int cy, char *str) { //DrawString (cx, cy, str, 255); while (*str) { M_DrawCharacter (cx, cy, *str, 255,255,255,255, false); str++; cx += MENU_FONT_SIZE; } } void M_DrawPic (int x, int y, char *pic) { R_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; int w,h; if ( !cached ) { int i; for ( i = 0; i < NUM_CURSOR_FRAMES; i++ ) { Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i ); R_DrawFindPic( cursorname ); } cached = true; } Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f ); R_DrawGetPicSize( &w, &h, cursorname ); R_DrawStretchPic ( x, y, scaledVideo(w), scaledVideo(h), cursorname, 1.0); //R_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, 255,255,255,255, false); for (n = 0; n < lines; n++) { cy += MENU_FONT_SIZE; M_DrawCharacter (cx, cy, 4, 255,255,255,255, false); } M_DrawCharacter (cx, cy+MENU_FONT_SIZE, 7, 255,255,255,255, false); // draw middle cx += MENU_FONT_SIZE; while (width > 0) { cy = y; M_DrawCharacter (cx, cy, 2, 255,255,255,255, false); for (n = 0; n < lines; n++) { cy += MENU_FONT_SIZE; M_DrawCharacter (cx, cy, 5, 255,255,255,255, false); } M_DrawCharacter (cx, cy+MENU_FONT_SIZE, 8, 255,255,255,255, false); width -= 1; cx += MENU_FONT_SIZE; } // draw right side cy = y; M_DrawCharacter (cx, cy, 3, 255,255,255,255, false); for (n = 0; n < lines; n++) { cy += MENU_FONT_SIZE; M_DrawCharacter (cx, cy, 6, 255,255,255,255, false); } M_DrawCharacter (cx, cy+MENU_FONT_SIZE, 9, 255,255,255,255, false); } /* ======================================================================= MAIN MENU ======================================================================= */ #define MAIN_ITEMS 5 char *main_names[] = { "m_main_game", "m_main_multiplayer", "m_main_options", "m_main_video", "m_main_quit", 0 }; void findMenuCoords (int *xoffset, int *ystart, int *totalheight, int *widest) { //float ratio; int w, h, i; *totalheight = 0; *widest = -1; for ( i = 0; main_names[i] != 0; i++ ) { R_DrawGetPicSize( &w, &h, main_names[i] ); /*if (w) { ratio = 32.0/(float)h; h = 32; w *= ratio; }*/ if ( w > *widest ) *widest = w; *totalheight += ( h + 12 ); } *ystart = ( viddef.height / 2 - scaledVideo(110) ); *xoffset = ( viddef.width - scaledVideo(*widest) + scaledVideo(70) ) / 2; // *xoffset = ( viddef.width - scaledVideo(*widest) )/ 2 + scaledVideo(30); } void M_Main_Draw (void) { int i; int w, h, last_h; int ystart; int xoffset; int widest = -1; int totalheight = 0; char litname[80]; findMenuCoords(&xoffset, &ystart, &totalheight, &widest); for ( i = 0; main_names[i] != 0; i++ ) { if ( i != m_main_cursor ) { R_DrawGetPicSize( &w, &h, main_names[i] ); R_DrawStretchPic ( xoffset, ystart + scaledVideo(i * 40 + 13), scaledVideo(w), scaledVideo(h), main_names[i], 1.0); //R_DrawPic( xoffset, ystart + i * 40 + 13, main_names[i] ); } } strcpy( litname, main_names[m_main_cursor] ); strcat( litname, "_sel" ); R_DrawGetPicSize( &w, &h, litname ); R_DrawStretchPic ( xoffset, ystart + scaledVideo(m_main_cursor * 40 + 13), scaledVideo(w+2), scaledVideo(h+2), litname, 1.0); //R_DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname ); M_DrawCursor( xoffset - scaledVideo(25), ystart + scaledVideo(m_main_cursor * 40 + 11), (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES ); R_DrawGetPicSize( &w, &h, "m_main_plaque" ); R_DrawStretchPic ( xoffset - scaledVideo(w/2 + 50), ystart + scaledVideo(10), scaledVideo(w), scaledVideo(h), "m_main_plaque", 1.0); //R_DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" ); last_h = h; R_DrawGetPicSize( &w, &h, "m_main_logo" ); R_DrawStretchPic ( xoffset - scaledVideo(w/2 + 50), ystart + scaledVideo(last_h) + scaledVideo(30), scaledVideo(w), scaledVideo(h), "m_main_logo", 1.0); //R_DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" ); } typedef struct { int min[2]; int max[2]; void (*OpenMenu)(void); } mainmenuobject_t; void addButton (mainmenuobject_t *thisObj, int index, int x, int y) { float ratio; //char *name; int w, h; R_DrawGetPicSize( &w, &h, main_names[index]); if (w) { ratio = 32.0/(float)h; h = 32; w *= ratio; } thisObj->min[0] = x; thisObj->max[0] = x + scaledVideo(w); thisObj->min[1] = y; thisObj->max[1] = y + scaledVideo(h); switch (index) { case 0: thisObj->OpenMenu = M_Menu_Game_f; case 1: thisObj->OpenMenu = M_Menu_Multiplayer_f; case 2: thisObj->OpenMenu = M_Menu_Options_f; case 3: thisObj->OpenMenu = M_Menu_Video_f; case 4: thisObj->OpenMenu = M_Menu_Quit_f; } } void openMenuFromMain (void) { 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; } } int MainMenuMouseHover; void CheckMainMenuMouse (void) { int ystart; int xoffset; int widest; int totalheight; int i, oldhover; char *sound = NULL; mainmenuobject_t buttons[MAIN_ITEMS]; oldhover = MainMenuMouseHover; MainMenuMouseHover = 0; findMenuCoords(&xoffset, &ystart, &totalheight, &widest); for ( i = 0; main_names[i] != 0; i++ ) addButton (&buttons[i], i, xoffset, ystart + scaledVideo(i * 40 + 13)); //Exit with double click 2nd mouse button if (!cursor.buttonused[MOUSEBUTTON2] && cursor.buttonclicks[MOUSEBUTTON2]==2) { M_PopMenu(); sound = menu_out_sound; cursor.buttonused[MOUSEBUTTON2] = true; cursor.buttonclicks[MOUSEBUTTON2] = 0; } for (i=MAIN_ITEMS-1;i>=0;i--) { if (cursor.x>=buttons[i].min[0] && cursor.x<=buttons[i].max[0] && cursor.y>=buttons[i].min[1] && cursor.y<=buttons[i].max[1]) { if (cursor.mouseaction) m_main_cursor = i; MainMenuMouseHover = 1 + i; if (oldhover == MainMenuMouseHover && MainMenuMouseHover-1 == m_main_cursor && !cursor.buttonused[MOUSEBUTTON1] && cursor.buttonclicks[MOUSEBUTTON1]==1) { openMenuFromMain(); sound = menu_move_sound; cursor.buttonused[MOUSEBUTTON1] = true; cursor.buttonclicks[MOUSEBUTTON1] = 0; } break; } } if (!MainMenuMouseHover) { cursor.buttonused[MOUSEBUTTON1] = false; cursor.buttonclicks[MOUSEBUTTON1] = 0; cursor.buttontime[MOUSEBUTTON1] = 0; } cursor.mouseaction = false; if ( sound ) S_StartLocalSound( sound ); } const char *M_Main_Key (int key) { const char *sound = menu_move_sound; switch (key) { case K_ESCAPE: #ifdef ERASER_COMPAT_BUILD // special hack for Eraser build if (cls.state == ca_disconnected) M_Menu_Quit_f (); else M_PopMenu (); #else // Knightmare- can't exit menu if disconnected, // so restart demo loop if (cls.state == ca_disconnected) Cbuf_AddText ("d1\n"); M_PopMenu (); #endif 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; } } return NULL; } void M_Menu_Main_f (void) { M_PushMenu (M_Main_Draw, M_Main_Key); } /* ======================================================================= GALLERY MENU ======================================================================= */ #if 0 void M_Menu_Gallery_f( void ) { extern void Gallery_MenuDraw( void ); extern const char *Gallery_MenuKey( int key ); M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey ); } #endif /* ======================================================================= QUIT MENU ======================================================================= */ const char *M_Quit_Key (int key) { switch (key) { case K_ESCAPE: case 'n': case 'N': M_PopMenu (); break; case 'Y': case 'y': cls.key_dest = key_console; CL_Quit_f (); break; default: break; } return NULL; } void M_Quit_Draw (void) { int w, h; R_DrawGetPicSize (&w, &h, "quit"); R_DrawStretchPic ( (viddef.width-scaledVideo(w))/2, (viddef.height-scaledVideo(h))/2, scaledVideo(w), scaledVideo(h), "quit", 1.0); //R_DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit"); } void M_Menu_Quit_f (void) { M_PushMenu (M_Quit_Draw, M_Quit_Key); } //============================================================================= /* Menu Subsystem */ /* ================= M_Init ================= */ void M_Init (void) { // Knightmare- init this cvar here so M_Print can use it if (!alt_text_color) alt_text_color = Cvar_Get ("alt_text_color", "2", CVAR_ARCHIVE); Cmd_AddCommand ("menu_main", M_Menu_Main_f); Cmd_AddCommand ("menu_game", M_Menu_Game_f); Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f); Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f); Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f); Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f); Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f); Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f); Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f); Cmd_AddCommand ("menu_downloadoptions", M_Menu_DownloadOptions_f); Cmd_AddCommand ("menu_credits", M_Menu_Credits_f ); Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f ); Cmd_AddCommand ("menu_video", M_Menu_Video_f); Cmd_AddCommand ("menu_video_advanced", M_Menu_Video_Advanced_f); Cmd_AddCommand ("menu_options", M_Menu_Options_f); Cmd_AddCommand ("menu_keys", M_Menu_Keys_f); Cmd_AddCommand ("menu_quit", M_Menu_Quit_f); } /* ================================= Menu Mouse Cursor - psychospaz ================================= */ void refreshCursorMenu (void) { cursor.menu = NULL; } void refreshCursorLink (void) { cursor.menuitem = NULL; } int Slider_CursorPositionX ( menuslider_s *s ) { float range; range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue ); if ( range < 0) range = 0; if ( range > 1) range = 1; return ( int )( scaledVideo(MENU_FONT_SIZE) + RCOLUMN_OFFSET + (SLIDER_RANGE)*scaledVideo(MENU_FONT_SIZE) * range ); } int newSliderValueForX (int x, menuslider_s *s) { float newValue; int newValueInt; int pos = x - scaledVideo(MENU_FONT_SIZE + RCOLUMN_OFFSET + s->generic.x) - s->generic.parent->x; newValue = ((float)pos)/((SLIDER_RANGE-1)*scaledVideo(MENU_FONT_SIZE)); newValueInt = s->minvalue + newValue * (float)( s->maxvalue - s->minvalue ); return newValueInt; } void Slider_CheckSlide( menuslider_s *s ) { if ( s->curvalue > s->maxvalue ) s->curvalue = s->maxvalue; else if ( s->curvalue < s->minvalue ) s->curvalue = s->minvalue; if ( s->generic.callback ) s->generic.callback( s ); } void Menu_DragSlideItem (menuframework_s *menu, void *menuitem) { // menucommon_s *item = ( menucommon_s * ) menuitem; menuslider_s *slider = ( menuslider_s * ) menuitem; slider->curvalue = newSliderValueForX(cursor.x, slider); Slider_CheckSlide ( slider ); } void Menu_ClickSlideItem (menuframework_s *menu, void *menuitem) { int min, max; menucommon_s *item = ( menucommon_s * ) menuitem; menuslider_s *slider = ( menuslider_s * ) menuitem; min = menu->x + scaledVideo(item->x + Slider_CursorPositionX(slider) - 4); max = menu->x + scaledVideo(item->x + Slider_CursorPositionX(slider) + 4); if (cursor.x < min) Menu_SlideItem( menu, -1 ); if (cursor.x > max) Menu_SlideItem( menu, 1 ); } void CheckQuitMenuMouse(void) { int maxs[2], mins[2]; int w, h; R_DrawGetPicSize (&w, &h, "quit"); mins[0] = (viddef.width-w)/2; maxs[0] = mins[0] + w; mins[1] = (viddef.height-h)/2; maxs[1] = mins[1] + h; if (cursor.x>=mins[0] && cursor.x<=maxs[0] && cursor.y>=mins[1] && cursor.y<=maxs[1]) { if (!cursor.buttonused[MOUSEBUTTON2] && cursor.buttonclicks[MOUSEBUTTON2]==2) { M_PopMenu (); cursor.buttonused[MOUSEBUTTON2] = true; cursor.buttonclicks[MOUSEBUTTON2] = 0; } if (!cursor.buttonused[MOUSEBUTTON1] && cursor.buttonclicks[MOUSEBUTTON1]==2) { CL_Quit_f (); cursor.buttonused[MOUSEBUTTON1] = true; cursor.buttonclicks[MOUSEBUTTON1] = 0; } } } void M_Think_MouseCursor (void) { char * sound = NULL; menuframework_s *m = (menuframework_s *)cursor.menu; if (m_drawfunc == M_Main_Draw) //have to hack for main menu :p { CheckMainMenuMouse(); return; } if (m_drawfunc == M_Quit_Draw) { CheckQuitMenuMouse(); return; } if (m_drawfunc == M_Credits_MenuDraw) //have to hack for credits :p { if (cursor.buttonclicks[MOUSEBUTTON2]) { cursor.buttonused[MOUSEBUTTON2] = true; cursor.buttonclicks[MOUSEBUTTON2] = 0; cursor.buttonused[MOUSEBUTTON1] = true; cursor.buttonclicks[MOUSEBUTTON1] = 0; S_StartLocalSound( menu_out_sound ); if (creditsBuffer) FS_FreeFile (creditsBuffer); M_PopMenu(); return; } } //mouse clicking on the player model menu... if (m_drawfunc == PlayerConfig_MenuDraw && menu_scale->value && viddef.width >= MENU_STATIC_WIDTH) PlayerConfig_MouseClick(); if (m_drawfunc == Options_MenuDraw && options_menu->value==3) MenuCrosshair_MouseClick(); if (!m) return; //Exit with double click 2nd mouse button if (cursor.menuitem) { //MOUSE1 if (cursor.buttondown[MOUSEBUTTON1]) { if (cursor.menuitemtype == MENUITEM_SLIDER) { Menu_DragSlideItem(m, cursor.menuitem); } else if (!cursor.buttonused[MOUSEBUTTON1] && cursor.buttonclicks[MOUSEBUTTON1]) { if (cursor.menuitemtype == MENUITEM_ROTATE) { if (menu_rotate->value) Menu_SlideItem( m, -1 ); else Menu_SlideItem( m, 1 ); sound = menu_move_sound; cursor.buttonused[MOUSEBUTTON1] = true; } else { cursor.buttonused[MOUSEBUTTON1] = true; Menu_MouseSelectItem( cursor.menuitem ); sound = menu_move_sound; } } } //MOUSE2 if (cursor.buttondown[MOUSEBUTTON2] && cursor.buttonclicks[MOUSEBUTTON2]) { if (cursor.menuitemtype == MENUITEM_SLIDER && !cursor.buttonused[MOUSEBUTTON2]) { Menu_ClickSlideItem(m, cursor.menuitem); sound = menu_move_sound; cursor.buttonused[MOUSEBUTTON2] = true; } else if (!cursor.buttonused[MOUSEBUTTON2]) { if (cursor.menuitemtype == MENUITEM_ROTATE) { if (menu_rotate->value) Menu_SlideItem( m, 1 ); else Menu_SlideItem( m, -1 ); sound = menu_move_sound; cursor.buttonused[MOUSEBUTTON2] = true; } } } } else if (!cursor.buttonused[MOUSEBUTTON2] && cursor.buttonclicks[MOUSEBUTTON2]==2 && cursor.buttondown[MOUSEBUTTON2]) { if (m_drawfunc==PlayerConfig_MenuDraw) PConfigAccept(); if (m_drawfunc==Options_MenuDraw && options_menu->value>0) { Cvar_SetValue( "options_menu", 0 ); refreshCursorLink(); } else M_PopMenu(); sound = menu_out_sound; cursor.buttonused[MOUSEBUTTON2] = true; cursor.buttonclicks[MOUSEBUTTON2] = 0; cursor.buttonused[MOUSEBUTTON1] = true; cursor.buttonclicks[MOUSEBUTTON1] = 0; } if ( sound ) S_StartLocalSound( sound ); } void M_Draw_Cursor (void) { float alpha = 1, scale = 1; int w,h; char *overlay = NULL; char *cur_img = NULL; if (m_drawfunc == M_Main_Draw) { if (MainMenuMouseHover) { if ((cursor.buttonused[0] && cursor.buttonclicks[0]) || (cursor.buttonused[1] && cursor.buttonclicks[1])) { cur_img = "/gfx/m_cur_click.pcx"; alpha = 0.85 + 0.15*sin(anglemod(cl.time*0.005)); } else { cur_img = "/gfx/m_cur_hover.pcx"; alpha = 0.85 + 0.15*sin(anglemod(cl.time*0.005)); } } else cur_img = "/gfx/m_cur_main.pcx"; overlay = "/gfx/m_cur_over.pcx"; } else { if (cursor.menuitem) { if (cursor.menuitemtype == MENUITEM_TEXT) { cur_img = "/gfx/m_cur_text.pcx"; } else { if ((cursor.buttonused[0] && cursor.buttonclicks[0]) || (cursor.buttonused[1] && cursor.buttonclicks[1])) { cur_img = "/gfx/m_cur_click.pcx"; alpha = 0.85 + 0.15*sin(anglemod(cl.time*0.005)); } else { cur_img = "/gfx/m_cur_hover.pcx"; alpha = 0.85 + 0.15*sin(anglemod(cl.time*0.005)); } overlay = "/gfx/m_cur_over.pcx"; } } else { cur_img = "/gfx/m_cur_main.pcx"; overlay = "/gfx/m_cur_over.pcx"; } } if (cur_img) { R_DrawGetPicSize( &w, &h, cur_img ); R_DrawScaledPic( cursor.x - w/2, cursor.y - h/2, scaledVideo(scale), alpha, cur_img, true, false); if (overlay) { R_DrawGetPicSize( &w, &h, "/gfx/m_cur_over.pcx" ); R_DrawScaledPic( cursor.x - w/2, cursor.y - h/2, scaledVideo(scale), 1, overlay, true, false); } } } /*void M_Draw_Cursor (void) { int w,h; //get sizing vars R_DrawGetPicSize( &w, &h, "m_mouse_cursor" ); w = scaledVideo(w)*0.5; h = scaledVideo(h)*0.5; R_DrawStretchPic (cursor.x-w/2, cursor.y-h/2, w, h, "m_mouse_cursor", 1.0); }*/ void InitMenuScale (void) { //this is for scaling the menu... //this is kinda overkill, but whatever... // Knightmare- allow disabling of menu scaling // also, don't scale if < 800x600, then it would be smaller if (menu_scale->value && viddef.width > MENU_STATIC_WIDTH ) { menuScale.x = viddef.width/MENU_STATIC_WIDTH; menuScale.y = viddef.height/MENU_STATIC_HEIGHT; //menuScale.avg = (menuScale.x + menuScale.y)*0.5f; menuScale.avg = min(menuScale.x, menuScale.y); // use smaller value instead of average } else { menuScale.x = 1; menuScale.y = 1; menuScale.avg = 1; } } /* ================= M_Draw ================= */ void M_Draw (void) { if (cls.key_dest != key_menu) return; // Knigthmare- added Psychospaz's scaled menu stuff InitMenuScale(); // repaint everything next frame SCR_DirtyScreen (); // dim everything behind it down if (cl.cinematictime > 0 || cls.state == ca_disconnected) { if (R_DrawFindPic("/gfx/menu_background.pcx")) { R_DrawStretchPic (0, 0, viddef.width, viddef.height, "/gfx/menu_background.pcx", 1.0); //R_DrawFadeScreen (); } else R_DrawFill (0,0,viddef.width, viddef.height, 0); } // ingame menu uses alpha else if (R_DrawFindPic("/gfx/menu_background.pcx")) R_DrawStretchPic (0, 0, viddef.width, viddef.height, "/gfx/menu_background.pcx", menu_alpha->value); else R_DrawFadeScreen (); // Knigthmare- added Psychospaz's mouse support refreshCursorMenu(); m_drawfunc (); // delay playing the enter sound until after the // menu has been drawn, to avoid delay while // caching images if (m_entersound) { S_StartLocalSound( menu_in_sound ); m_entersound = false; } // Knigthmare- added Psychospaz's mouse support //menu cursor for mouse usage :) M_Draw_Cursor(); } /* ================= M_Keydown ================= */ void M_Keydown (int key) { const char *s; if (m_keyfunc) if ( ( s = m_keyfunc( key ) ) != 0 ) S_StartLocalSound( ( char * ) s ); }