From c068f22329d5cc722622a2183bbb22eef2093df7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Aug 2026 11:16:07 +0200 Subject: initial import --- src/parsec/m_list.cpp | 1030 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1030 insertions(+) create mode 100644 src/parsec/m_list.cpp (limited to 'src/parsec/m_list.cpp') diff --git a/src/parsec/m_list.cpp b/src/parsec/m_list.cpp new file mode 100644 index 0000000..09b58f3 --- /dev/null +++ b/src/parsec/m_list.cpp @@ -0,0 +1,1030 @@ +/* + * PARSEC - List Windows + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:37 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1998-2000 + * Copyright (c) Andreas Varga 1999-2000 + * + * 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 + */ + +// C library +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" +#include "inp_defs.h" +#include "net_defs.h" +#include "sys_defs.h" + +// drawing subsystem +#include "d_font.h" + +// local module header +#include "m_list.h" + +// proprietary module headers +#include "con_aux.h" +#include "e_color.h" +#include "e_demo.h" +#include "e_draw.h" +#include "h_cockpt.h" +#include "m_main.h" + + + +// generic string paste area -------------------------------------------------- +// +#define PASTE_STR_LEN 2047 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// string constants ----------------------------------------------------------- +// +static char playerlist_caption_str[] = "connected players"; +static char playerlist_name_str[] = "name"; +static char playerlist_kills_str[] = "kills"; +static char playerlist_kill_limit_str[] = "kill limit has been reached!"; + +static char demolist_caption_str[] = " available demos "; +static char demolist_freeflight_str[] = " free flight mode "; + +static char serverlist_caption_str[] = " Click Connect "; +static char serverlist_peertopeer[] = "name "; + + +// pointer to current caption of player list window --------------------------- +// +static char *playerlist_caption; + + +// player and demo list window configuration ---------------------------------- +// +#define LIST_POS_RIGHT 0 +#define LIST_POS_LEFT ( m_sintab_size - 1 ) + +#define LIST_SLIDE_SPEED_MENU 12 +#define LIST_SLIDE_SPEED_GAME 6 + +#define LIST_MARGIN 4 + + +// player and demo list state variables --------------------------------------- +// +static int list_slidepos = LIST_POS_RIGHT; +static int list_slidetarget = LIST_POS_LEFT; +static refframe_t list_lastref = REFFRAME_INVALID; + +static int cur_demolist_selindx = 0; +static int num_listed_demos = 0; + + +// default list window -------------------------------------------------------- +// +#if defined ( CLIENT_BUILD_SELF_RUNNING_DEMO ) || defined ( CLIENT_BUILD_LAN_ONLY_VERSION ) + #define LISTWIN_DEFAULT LISTWIN_DEMOLIST +#else + #define LISTWIN_DEFAULT LISTWIN_SERVERLIST +#endif + + +// currently active mode of list window --------------------------------------- +// +PUBLIC int listwin_mode = LISTWIN_DEFAULT; + + +// flag whether list window is active (visible and has focus) ----------------- +// +PUBLIC int listwin_active = FALSE; + + +// return current selection in demo list -------------------------------------- +// +int DemoListSelection() +{ + if ( cur_demolist_selindx < num_listed_demos ) { + + return cur_demolist_selindx; + + } else { + + // this indicates "free flight mode" + return -1; + } +} + + +// one item up in demo list --------------------------------------------------- +// +void DemoListCursorUp() +{ + // wrap around to free flight mode + if ( --cur_demolist_selindx < 0 ) + cur_demolist_selindx = num_listed_demos; + AUD_Select2(); +} + + +// one item down in demo list ------------------------------------------------- +// +void DemoListCursorDown() +{ + // wrap around to first demo + if ( ++cur_demolist_selindx > num_listed_demos ) + cur_demolist_selindx = 0; + AUD_Select2(); +} + + +// current metrics of demo list window contents ------------------------------- +// +static list_window_metrics_s demolist_content_metrics = { FALSE }; + + +// set mouse pointer into demo list window ------------------------------------ +// +void DemoListMouseSet() +{ + if ( demolist_content_metrics.valid ) { + + int chwidth = demolist_content_metrics.chwidth; + int text_x = demolist_content_metrics.text_x; + int text_y = demolist_content_metrics.text_y; + int linemid2 = demolist_content_metrics.maxcontwidth * chwidth / 2; + int lineh2 = demolist_content_metrics.chheight / 2; + + // set mouse pos + mousestate_s mousestate; + mousestate.xpos = (float)( text_x + linemid2 ) / Screen_Width; + mousestate.ypos = (float)( text_y + lineh2 ) / Screen_Height; + INPs_MouseSetState( &mousestate ); + } +} + + +// detect whether mouse position is over demo list item ----------------------- +// +PRIVATE +int MouseOverDemoListItem( int mousex, int mousey ) +{ + if ( !demolist_content_metrics.valid ) + return MOUSE_OVER_NOTHING; + + if ( !SlideFinishedListWindow() ) + return MOUSE_OVER_NOTHING; + + int chwidth = demolist_content_metrics.chwidth; + int chheight = demolist_content_metrics.chheight; + int text_x = demolist_content_metrics.text_x; + int text_y = demolist_content_metrics.text_y; + int linewidth = demolist_content_metrics.maxcontwidth * chwidth; + + // number of items must be guarded against window height overflow + int numitems = num_registered_demos + 1; + + // caption: 2 lines, divider line: 1 line + if ( numitems > demolist_content_metrics.maxcontheight - 3 ) { + numitems = demolist_content_metrics.maxcontheight - 3; + } + + // check against demolist items + for ( int mid = 0; mid < numitems; mid++ ) { + + if ( ( mousex >= text_x ) && ( mousex < ( text_x + linewidth ) ) && + ( mousey >= text_y ) && ( mousey < ( text_y + chheight ) ) ) { + + // set selected index directly + if ( cur_demolist_selindx != mid ) + AUD_Select2(); + cur_demolist_selindx = mid; + + return MOUSE_OVER_OPTION; + } + + text_y += chheight; + } + + return MOUSE_OVER_NOTHING; +} + + +// detect whether mouse position is over player list item --------------------- +// +PRIVATE +int MouseOverPlayerListItem( int mousex, int mousey ) +{ + return MOUSE_OVER_NOTHING; +} + + +// detect whether mouse position is over server list item --------------------- +// +PRIVATE +int MouseOverServerListItem( int mousex, int mousey ) +{ + return MOUSE_OVER_NOTHING; +} + + +// detect whether mouse position is over item of current list ----------------- +// +int MouseOverListItem( int mousex, int mousey ) +{ + int item = MOUSE_OVER_NOTHING; + + switch ( listwin_mode ) { + + case LISTWIN_DEMOLIST: + item = MouseOverDemoListItem( mousex, mousey ); + break; + + case LISTWIN_PLAYERLIST: + item = MouseOverPlayerListItem( mousex, mousey ); + break; + + case LISTWIN_SERVERLIST: + item = MouseOverServerListItem( mousex, mousey ); + break; + } + + return item; +} + + +// set position and slide target for list window to left (in) ----------------- +// +void MoveInListWindow() +{ + list_slidepos = LIST_POS_LEFT; + list_slidetarget = list_slidepos; +} + + +// set position and slide target for list window to right (out) --------------- +// +void MoveOutListWindow() +{ + list_slidepos = LIST_POS_RIGHT; + list_slidetarget = list_slidepos; +} + + +// set slide target for list window to left (in) ------------------------------ +// +void SlideInListWindow() +{ + list_slidetarget = LIST_POS_LEFT; +} + + +// set slide target for list window to right (out) ---------------------------- +// +void SlideOutListWindow() +{ + list_slidetarget = LIST_POS_RIGHT; +} + + +// check if list window is at its desired slide position ---------------------- +// +int SlideFinishedListWindow() +{ + return ( list_slidepos == list_slidetarget ); +} + + +// slide the list to its specifed target x position --------------------------- +// +PRIVATE +int SlideListWindow() +{ + // skip drawing code if list slided out + if ( list_slidepos == list_slidetarget ) { + list_lastref = REFFRAME_INVALID; + return ( list_slidepos != LIST_POS_RIGHT ); + } + + // twice as fast in game than in menu + int slidespeed = InFloatingMenu ? + LIST_SLIDE_SPEED_MENU : LIST_SLIDE_SPEED_GAME; + + if ( list_slidepos < list_slidetarget ) { + + // slide right + refframe_t refframecount = SYSs_GetRefFrameCount(); + if ( list_lastref == REFFRAME_INVALID ) { + list_lastref = refframecount; + } else { + refframe_t delta = refframecount - list_lastref; + for ( ; delta >= slidespeed; delta -= slidespeed ) { + list_slidepos++; + if ( list_slidepos >= list_slidetarget ) { + list_slidepos = list_slidetarget; + list_lastref = REFFRAME_INVALID; + break; + } + list_lastref += slidespeed; + } + } + + } else { + + // slide left + refframe_t refframecount = SYSs_GetRefFrameCount(); + if ( list_lastref == REFFRAME_INVALID ) { + list_lastref = refframecount; + } else { + refframe_t delta = refframecount - list_lastref; + for ( ; delta >= slidespeed; delta -= slidespeed ) { + list_slidepos--; + if ( list_slidepos <= list_slidetarget ) { + list_slidepos = list_slidetarget; + list_lastref = REFFRAME_INVALID; + break; + } + list_lastref += slidespeed; + } + } + } + + return TRUE; +} + + +// type for writestring function pointer -------------------------------------- +// +typedef void (*WSFP)( ... ); + +//NOTE: +// this declaration is in global scope because of the extern "C". +// only gcc needs the otherwise redundant curly braces. + + +// draw horizontal divider line built from minus signs ------------------------ +// +static +void DrawDividerLine( WSFP wstrfp, int lx, int ly, int len ) +{ + ASSERT( wstrfp != NULL ); + + ASSERT( len <= PASTE_STR_LEN ); + int dpos = 0; + for ( dpos = 0; dpos < len; dpos++ ) { + paste_str[ dpos ] = '-'; + } + paste_str[ dpos ] = 0; + + wstrfp( paste_str, lx, ly, TRTAB_PANELTEXT ); +} + + +// draw translucent background window for demo list window -------------------- +// +PRIVATE +void DrawDemoListFrame() +{ + int frame_l = demolist_content_metrics.frame_l; + int frame_r = demolist_content_metrics.frame_r; + int frame_t = demolist_content_metrics.frame_t; + int frame_b = demolist_content_metrics.frame_b; + int chwidth = demolist_content_metrics.chwidth; + int chheight = demolist_content_metrics.chheight; + int text_x = demolist_content_metrics.text_x; + int text_y = demolist_content_metrics.text_y; + int maxcontwidth = demolist_content_metrics.maxcontwidth; + int maxcontheight = demolist_content_metrics.maxcontheight; + + int backx = text_x - frame_l * chwidth; + int backy = text_y - frame_t * chheight; + int backw = ( frame_l + frame_r + maxcontwidth ) * chwidth; + int backh = ( frame_t + frame_b + maxcontheight ) * chheight; + + DRAW_ClippedTrRect( backx, backy, backw, backh, TRTAB_PANELBACK ); +} + + +// draw caption of demo list window ------------------------------------------- +// +PRIVATE +void DrawDemoListCaption( WSFP wstrfp ) +{ + unsigned int chwidth = demolist_content_metrics.chwidth; + unsigned int chheight = demolist_content_metrics.chheight; + int text_x = demolist_content_metrics.text_x; + int text_y = demolist_content_metrics.text_y; + unsigned int maxcontwidth = demolist_content_metrics.maxcontwidth; + unsigned int maxcontheight = demolist_content_metrics.maxcontheight; + + // draw caption + ASSERT( maxcontwidth >= strlen( demolist_caption_str ) ); + int xofs = ( ( maxcontwidth - strlen( demolist_caption_str ) ) * chwidth ) / 2; + wstrfp( demolist_caption_str, text_x + xofs, text_y, TRTAB_PANELTEXT ); + text_y += chheight * 2; + + // draw separator + DrawDividerLine( wstrfp, text_x, text_y, maxcontwidth ); + text_y += chheight; + + demolist_content_metrics.text_y = text_y; +} + + +// draw all demo list items (demo names) -------------------------------------- +// +PRIVATE +void DrawDemoListItems( WSFP wstrfp ) +{ + unsigned int chwidth = demolist_content_metrics.chwidth; + unsigned int chheight = demolist_content_metrics.chheight; + int text_x = demolist_content_metrics.text_x; + int text_y = demolist_content_metrics.text_y; + unsigned int maxcontwidth = demolist_content_metrics.maxcontwidth; + unsigned int maxcontheight = demolist_content_metrics.maxcontheight; + + // display all demos + unsigned int lid = 0; + + for ( unsigned int lid = 0; lid < (unsigned int)num_registered_demos; lid++ ) { + + // caption: 2 lines, divider line: 1 line, free flight: 1 line + if ( lid >= maxcontheight - 4 ) + break; + + char *strp = registered_demo_titles[ lid ] ? + registered_demo_titles[ lid ] : registered_demo_names[ lid ]; + + ASSERT( maxcontwidth >= strlen( strp ) ); + int xofs = ( ( maxcontwidth - strlen( strp ) ) * chwidth ) / 2; + + wstrfp( strp, text_x + xofs, text_y, TRTAB_PANELTEXT ); + if ( ( (unsigned int)cur_demolist_selindx == lid ) && listwin_active ) { + wstrfp( strp, text_x + xofs, text_y, TRTAB_PANELTEXT ); + } + + text_y += chheight; + } + + // remember for cursor movement and selection + num_listed_demos = lid; + + // display free flight option + text_x += ( ( maxcontwidth - strlen( demolist_freeflight_str ) ) * chwidth ) / 2; + wstrfp( demolist_freeflight_str, text_x, text_y, TRTAB_PANELTEXT ); + if ( ( cur_demolist_selindx == num_listed_demos ) && listwin_active ) { + wstrfp( demolist_freeflight_str, text_x, text_y, TRTAB_PANELTEXT ); + } +} + + +// calc and store metrics for demo list window -------------------------------- +// +PRIVATE +void CalcDemoListContentMetrics() +{ + // bounds for content + int maxcontwidth = strlen( demolist_caption_str ) + LIST_MARGIN - 2; + int maxcontheight = 20; + + // ensure maximum content width is big enough + for ( int lid = 0; lid < num_registered_demos; lid++ ) { + int len = registered_demo_titles[ lid ] ? + strlen( registered_demo_titles[ lid ] ) : + strlen( registered_demo_names[ lid ] ); + if ( len > maxcontwidth ) { + maxcontwidth = len + LIST_MARGIN; + } + } + + extern int hud_line_dist; + + // font metrics + int chwidth = CharsetInfo[ HUD_CHARSETNO ].width; + int chheight = hud_line_dist; + + D_SetWStrContext( CharsetInfo[ HUD_CHARSETNO ].charsetpointer, + CharsetInfo[ HUD_CHARSETNO ].geompointer, + NULL, + CharsetInfo[ HUD_CHARSETNO ].width, + CharsetInfo[ HUD_CHARSETNO ].height ); + + // frame metrics + int frame_l = 1; + int frame_r = 1; + int frame_t = 2; + int frame_b = 1; + + // text position + int text_x = Screen_Width - ( frame_r + maxcontwidth ) * chwidth - 30; + if ( list_slidepos != -1 ) + text_x += m_sintab[ list_slidepos ]; + int text_y = InFloatingMenu ? 62 : 140; + + // store metrics + demolist_content_metrics.valid = TRUE; + demolist_content_metrics.frame_l = frame_l; + demolist_content_metrics.frame_r = frame_r; + demolist_content_metrics.frame_t = frame_t; + demolist_content_metrics.frame_b = frame_b; + demolist_content_metrics.chwidth = chwidth; + demolist_content_metrics.chheight = chheight; + demolist_content_metrics.text_x = text_x; + demolist_content_metrics.text_y = text_y; + demolist_content_metrics.maxcontwidth = maxcontwidth; + demolist_content_metrics.maxcontheight = maxcontheight; +} + + +// draw translucent window for demo list --------------------------------------- +// +PRIVATE +void DrawDemoListWindow() +{ + // slide the window if necessary + if ( !SlideListWindow() ) + return; + + CalcDemoListContentMetrics(); + + // check whether actual drawing disabled + if ( AUX_DISABLE_FLOATING_MENU_DRAWING ) + return; + + // determine whether translucency should be used + int translucent = VID_TRANSLUCENCY_SUPPORTED; + + // write text transparent only for color depths below 32 bit per pixel + WSFP wstrfp = translucent ? (WSFP)&D_WriteTrString : (WSFP)&D_WriteString; + + // draw frame + if ( translucent ) { + DrawDemoListFrame(); + } + + // draw caption + DrawDemoListCaption( wstrfp ); + + // draw items + DrawDemoListItems( wstrfp ); +} + + +// current metrics of player list window contents ----------------------------- +// +static list_window_metrics_s playerlist_content_metrics = { FALSE }; + + +// draw translucent background window for player list window ------------------ +// +PRIVATE +void DrawPlayerListFrame() +{ + int frame_l = playerlist_content_metrics.frame_l; + int frame_r = playerlist_content_metrics.frame_r; + int frame_t = playerlist_content_metrics.frame_t; + int frame_b = playerlist_content_metrics.frame_b; + int chwidth = playerlist_content_metrics.chwidth; + int chheight = playerlist_content_metrics.chheight; + int text_x = playerlist_content_metrics.text_x; + int text_y = playerlist_content_metrics.text_y; + int maxcontwidth = playerlist_content_metrics.maxcontwidth; + int maxcontheight = playerlist_content_metrics.maxcontheight; + + int backx = text_x - frame_l * chwidth; + int backy = text_y - frame_t * chheight; + int backw = ( frame_l + frame_r + maxcontwidth ) * chwidth; + int backh = ( frame_t + frame_b + maxcontheight ) * chheight; + + DRAW_ClippedTrRect( backx, backy, backw, backh, TRTAB_PANELBACK ); +} + + +// draw caption of player list window ----------------------------------------- +// +PRIVATE +void DrawPlayerListCaption( WSFP wstrfp ) +{ + unsigned int chwidth = playerlist_content_metrics.chwidth; + unsigned int chheight = playerlist_content_metrics.chheight; + int text_x = playerlist_content_metrics.text_x; + int text_y = playerlist_content_metrics.text_y; + unsigned int maxcontwidth = playerlist_content_metrics.maxcontwidth; + unsigned int maxcontheight = playerlist_content_metrics.maxcontheight; + + // draw list caption + ASSERT( maxcontwidth >= strlen( playerlist_caption ) ); + int xofs = ( ( maxcontwidth - strlen( playerlist_caption ) ) * chwidth ) / 2; + wstrfp( playerlist_caption, text_x + xofs, text_y, TRTAB_PANELTEXT ); + text_y += chheight * 2; + + // draw "name" and "kills" caption + wstrfp( playerlist_name_str, text_x, text_y, TRTAB_PANELTEXT ); + xofs = ( maxcontwidth - strlen( playerlist_kills_str ) ) * chwidth; + wstrfp( playerlist_kills_str, text_x + xofs, text_y, TRTAB_PANELTEXT ); + text_y += chheight; + + // draw separator + DrawDividerLine( wstrfp, text_x, text_y, maxcontwidth ); + text_y += chheight; + + playerlist_content_metrics.text_y = text_y; +} + + +// draw all player names and kills -------------------------------------------- +// +PRIVATE +void DrawPlayerListItems( WSFP wstrfp ) +{ + unsigned int chwidth = playerlist_content_metrics.chwidth; + unsigned int chheight = playerlist_content_metrics.chheight; + int text_x = playerlist_content_metrics.text_x; + int text_y = playerlist_content_metrics.text_y; + unsigned int maxcontwidth = playerlist_content_metrics.maxcontwidth; + unsigned int maxcontheight = playerlist_content_metrics.maxcontheight; + + //FIXME: this function is EXACT the same as M_STATUS::DrawStatusWindowItems + const char *voidstr = "-"; + + int sortfilter[ MAX_NET_ALLOC_SLOTS ]; + int sid = 0; + for ( sid = 0; sid < MAX_NET_ALLOC_SLOTS; sid++ ) { + sortfilter[ sid ] = 0; + } + + // print playerlist (optionally sorted by number of kills) + for ( int pid = 0; pid < MAX_NET_PROTO_PLAYERS; pid++ ) { + + int slot = pid; + int kills = -1; + + // search for highest kills if sorting enabled + if ( AUX_DISABLE_SORTED_PLAYERLIST ) { + kills = Player_KillStat[ pid ]; + } else { + + // invalidate slot + slot = -1; + + // sort for highest kills of connected players not yet displayed + for ( sid = 0; sid < MAX_NET_PROTO_PLAYERS; sid++ ) { + if ( !sortfilter[ sid ] && ( Player_KillStat[ sid ] > kills ) && Player_Status[ sid ] ) { + slot = sid; + kills = Player_KillStat[ sid ]; + } + } + + // check for valid slot + if ( slot != -1 ) { + + // do not consider slot in next round + sortfilter[ slot ] = 1; + + // invalidate slot if disconnected and not the local player + if ( !( ( Player_Status[ slot ] ) || ( slot == LocalPlayerId ) ) ) + slot = -1; + } + } + + // get name to be displayed + const char *strp = (slot != -1) ? Player_Name[ slot ] : voidstr; + if ( slot == LocalPlayerId ) + strp = LocalPlayerName; // so local name can be changed on the fly + + // write name + ASSERT( maxcontwidth >= strlen( strp ) ); + int xofs = ( ( maxcontwidth - strlen( strp ) ) * chwidth ) / 2; + wstrfp( strp, text_x, text_y, TRTAB_PANELTEXT ); + + // get kills to be displayed + char ckills_str[ 5 ] = ""; + if ( slot != -1 ) { + ASSERT( kills >= 0 ); + sprintf( ckills_str, "%d", kills ); + } else { + sprintf( ckills_str, "-" ); + } + + // write kill + xofs = ( maxcontwidth - strlen( ckills_str ) ) * chwidth; + wstrfp( ckills_str, text_x + xofs, text_y, TRTAB_PANELTEXT ); + + // advance to next line + text_y += chheight; + } +} + + +// calc and store metrics for player list window ------------------------------ +// +PRIVATE +void CalcPlayerListContentMetrics() +{ + // determine caption + extern int limit_reached; + playerlist_caption = limit_reached ? + playerlist_kill_limit_str : playerlist_caption_str; + + // bounds for content + unsigned int maxcontwidth = strlen( playerlist_caption ) + LIST_MARGIN - 2; + unsigned int maxcontheight = 20; + + // ensure maximum content width is big enough + for ( int lid = 0; lid < MAX_NET_PROTO_PLAYERS; lid++ ) { + if ( strlen( Player_Name[ lid ] ) > maxcontwidth ) { + maxcontwidth = strlen( Player_Name[ lid ] ) + LIST_MARGIN; + } + } + + // check local player name + if ( strlen( LocalPlayerName ) > maxcontwidth ) { + maxcontwidth = strlen( LocalPlayerName ) + LIST_MARGIN; + } + + extern int hud_line_dist; + + int chwidth = CharsetInfo[ HUD_CHARSETNO ].width; + int chheight = hud_line_dist; + + D_SetWStrContext( CharsetInfo[ HUD_CHARSETNO ].charsetpointer, + CharsetInfo[ HUD_CHARSETNO ].geompointer, + NULL, + CharsetInfo[ HUD_CHARSETNO ].width, + CharsetInfo[ HUD_CHARSETNO ].height ); + + // frame metrics + int frame_l = 1; + int frame_r = 1; + int frame_t = 2; + int frame_b = 1; + + // text position + int text_x = Screen_Width - ( frame_r + maxcontwidth ) * chwidth - 30; + if ( list_slidepos != -1 ) + text_x += m_sintab[ list_slidepos ]; + int text_y = InFloatingMenu ? 62 : (int)( 150 * Scaled_Screen_Height / 480 ); + + // store metrics + playerlist_content_metrics.valid = TRUE; + playerlist_content_metrics.frame_l = frame_l; + playerlist_content_metrics.frame_r = frame_r; + playerlist_content_metrics.frame_t = frame_t; + playerlist_content_metrics.frame_b = frame_b; + playerlist_content_metrics.chwidth = chwidth; + playerlist_content_metrics.chheight = chheight; + playerlist_content_metrics.text_x = text_x; + playerlist_content_metrics.text_y = text_y; + playerlist_content_metrics.maxcontwidth = maxcontwidth; + playerlist_content_metrics.maxcontheight = maxcontheight; +} + + +// draw remote player list ----------------------------------------------------- +// +void DrawRemotePlayerListWindow() +{ + // slide the window if necessary + if ( !SlideListWindow() ) + return; + + CalcPlayerListContentMetrics(); + + // check whether actual drawing disabled + if ( AUX_DISABLE_FLOATING_MENU_DRAWING ) + return; + + // determine whether translucency should be used + int translucent = VID_TRANSLUCENCY_SUPPORTED; + + // write text transparent only for color depths below 32 bit per pixel + WSFP wstrfp = translucent ? (WSFP)&D_WriteTrString : (WSFP)&D_WriteString; + + // draw frame + if ( translucent ) { + DrawPlayerListFrame(); + } + + // draw caption + DrawPlayerListCaption( wstrfp ); + + // draw items + DrawPlayerListItems( wstrfp ); +} + + +// current metrics of server list window contents ----------------------------- +// +static list_window_metrics_s serverlist_content_metrics = { FALSE }; + + +// draw translucent background window for server list window ------------------ +// +PRIVATE +void DrawServerListFrame() +{ + int frame_l = serverlist_content_metrics.frame_l; + int frame_r = serverlist_content_metrics.frame_r; + int frame_t = serverlist_content_metrics.frame_t; + int frame_b = serverlist_content_metrics.frame_b; + unsigned int chwidth = serverlist_content_metrics.chwidth; + unsigned int chheight = serverlist_content_metrics.chheight; + int text_x = serverlist_content_metrics.text_x; + int text_y = serverlist_content_metrics.text_y; + unsigned int maxcontwidth = serverlist_content_metrics.maxcontwidth; + unsigned int maxcontheight = serverlist_content_metrics.maxcontheight; + + int backx = text_x - frame_l * chwidth; + int backy = text_y - frame_t * chheight; + int backw = ( frame_l + frame_r + maxcontwidth ) * chwidth; + int backh = ( frame_t + frame_b + maxcontheight ) * chheight; + + DRAW_ClippedTrRect( backx, backy, backw, backh, TRTAB_PANELBACK ); +} + + +// draw caption of server list window ----------------------------------------- +// +PRIVATE +void DrawServerListCaption( WSFP wstrfp ) +{ + unsigned int chwidth = serverlist_content_metrics.chwidth; + unsigned int chheight = serverlist_content_metrics.chheight; + int text_x = serverlist_content_metrics.text_x; + int text_y = serverlist_content_metrics.text_y; + unsigned int maxcontwidth = serverlist_content_metrics.maxcontwidth; + unsigned int maxcontheight = serverlist_content_metrics.maxcontheight; + + // draw caption + ASSERT( maxcontwidth >= strlen( serverlist_caption_str ) ); + int xofs = ( ( maxcontwidth - strlen( serverlist_caption_str ) ) * chwidth ) / 2; + wstrfp( serverlist_caption_str, text_x + xofs, text_y, TRTAB_PANELTEXT ); + text_y += chheight * 2; + + // draw separator + DrawDividerLine( wstrfp, text_x, text_y, maxcontwidth ); + text_y += chheight; + + serverlist_content_metrics.text_y = text_y; +} + + +// draw all server names and kills -------------------------------------------- +// +PRIVATE +void DrawServerListItems( WSFP wstrfp ) +{ + unsigned int chwidth = serverlist_content_metrics.chwidth; + unsigned int chheight = serverlist_content_metrics.chheight; + int text_x = serverlist_content_metrics.text_x; + int text_y = serverlist_content_metrics.text_y; + unsigned int maxcontwidth = serverlist_content_metrics.maxcontwidth; + unsigned int maxcontheight = serverlist_content_metrics.maxcontheight; + + // print serverlist + int xofs = ( ( maxcontwidth - strlen( serverlist_peertopeer ) ) * chwidth ) / 2; + wstrfp( serverlist_peertopeer, text_x + xofs, text_y, TRTAB_PANELTEXT ); + text_y += chheight; + + serverlist_content_metrics.text_y = text_y; +} + + +// calc and store metrics for server list window ------------------------------ +// +PRIVATE +void CalcServerListContentMetrics() +{ + // bounds for content + unsigned int maxcontwidth = strlen( serverlist_caption_str ) + LIST_MARGIN - 2; + unsigned int maxcontheight = 20; +/* + // ensure maximum content width is big enough + for ( int lid = 0; lid < num_registered_demos; lid++ ) { + int len = registered_demo_titles[ lid ] ? + strlen( registered_demo_titles[ lid ] ) : + strlen( registered_demo_names[ lid ] ); + if ( len > maxcontwidth ) { + maxcontwidth = len + LIST_MARGIN; + } + } +*/ + extern int hud_line_dist; + + // font metrics + unsigned int chwidth = CharsetInfo[ HUD_CHARSETNO ].width; + unsigned int chheight = hud_line_dist; + + D_SetWStrContext( CharsetInfo[ HUD_CHARSETNO ].charsetpointer, + CharsetInfo[ HUD_CHARSETNO ].geompointer, + NULL, + CharsetInfo[ HUD_CHARSETNO ].width, + CharsetInfo[ HUD_CHARSETNO ].height ); + + // frame metrics + int frame_l = 1; + int frame_r = 1; + int frame_t = 2; + int frame_b = 1; + + // text position + int text_x = Screen_Width - ( frame_r + maxcontwidth ) * chwidth - 30; + if ( list_slidepos != -1 ) + text_x += m_sintab[ list_slidepos ]; + int text_y = InFloatingMenu ? 62 : 140; + + // store metrics + serverlist_content_metrics.valid = TRUE; + serverlist_content_metrics.frame_l = frame_l; + serverlist_content_metrics.frame_r = frame_r; + serverlist_content_metrics.frame_t = frame_t; + serverlist_content_metrics.frame_b = frame_b; + serverlist_content_metrics.chwidth = chwidth; + serverlist_content_metrics.chheight = chheight; + serverlist_content_metrics.text_x = text_x; + serverlist_content_metrics.text_y = text_y; + serverlist_content_metrics.maxcontwidth = maxcontwidth; + serverlist_content_metrics.maxcontheight = maxcontheight; +} + + +// draw server list ----------------------------------------------------------- +// +void DrawServerListWindow() +{ + // slide the window if necessary + if ( !SlideListWindow() ) + return; + + CalcServerListContentMetrics(); + + // check whether actual drawing disabled + if ( AUX_DISABLE_FLOATING_MENU_DRAWING ) + return; + + // determine whether translucency should be used + int translucent = VID_TRANSLUCENCY_SUPPORTED; + + // write text transparent only for color depths below 32 bit per pixel + WSFP wstrfp = translucent ? (WSFP)&D_WriteTrString : (WSFP)&D_WriteString; + + // draw frame + if ( translucent ) { + DrawServerListFrame(); + } + + // draw caption + DrawServerListCaption( wstrfp ); + + // draw items + DrawServerListItems( wstrfp ); +} + + +// draw translucent list window in menu (depending on current mode) ----------- +// +void DrawMenuListWindow() +{ + switch ( listwin_mode ) { + + case LISTWIN_DEMOLIST: + DrawDemoListWindow(); + break; + + case LISTWIN_PLAYERLIST: + DrawRemotePlayerListWindow(); + break; + + case LISTWIN_SERVERLIST: + DrawServerListWindow(); + break; + } +} + + + -- cgit v1.2.3