2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Inferno main menu .
*
*/
# include <stdio.h>
# include <string.h>
# include "menu.h"
# include "inferno.h"
# include "game.h"
# include "gr.h"
# include "key.h"
2011-01-02 11:25:51 +00:00
# include "mouse.h"
2006-03-20 17:12:09 +00:00
# include "iff.h"
# include "u_mem.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "bm.h"
# include "screens.h"
# include "joy.h"
2015-07-25 23:10:45 +00:00
# include "player.h"
2006-03-20 17:12:09 +00:00
# include "vecmat.h"
# include "effects.h"
2013-09-24 01:59:09 +00:00
# include "game.h"
2006-03-20 17:12:09 +00:00
# include "slew.h"
# include "gamemine.h"
# include "gamesave.h"
# include "palette.h"
# include "args.h"
# include "newdemo.h"
# include "timer.h"
# include "sounds.h"
# include "gameseq.h"
# include "text.h"
# include "gamefont.h"
# include "newmenu.h"
# include "scores.h"
# include "playsave.h"
# include "kconfig.h"
# include "titles.h"
# include "credits.h"
# include "texmap.h"
# include "polyobj.h"
# include "state.h"
# include "mission.h"
# include "songs.h"
2010-10-14 09:50:11 +00:00
# ifdef USE_SDLMIXER
2010-08-27 14:09:19 +00:00
# include "jukebox.h" // for jukebox_exts
2010-10-14 09:50:11 +00:00
# endif
2006-03-20 17:12:09 +00:00
# include "config.h"
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
# include "movie.h"
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
# include "gamepal.h"
# include "gauges.h"
# include "powerup.h"
# include "strutil.h"
2009-11-29 16:46:13 +00:00
# include "multi.h"
2012-11-02 17:35:57 +00:00
# include "vers_id.h"
2009-11-29 16:46:13 +00:00
# ifdef USE_UDP
# include "net_udp.h"
2009-11-24 09:48:53 +00:00
# endif
2006-03-20 17:12:09 +00:00
# ifdef EDITOR
# include "editor/editor.h"
2010-12-21 03:35:50 +00:00
# include "editor/kdefs.h"
2006-03-20 17:12:09 +00:00
# endif
2011-01-16 00:50:42 +00:00
# ifdef OGL
# include "ogl_init.h"
# endif
2015-04-19 04:18:49 +00:00
# include "physfs_list.h"
2006-03-20 17:12:09 +00:00
2014-07-05 16:48:12 +00:00
# include "dxxsconf.h"
2016-03-19 19:08:10 +00:00
# include "dsx-ns.h"
2014-09-28 23:28:56 +00:00
# include "compiler-make_unique.h"
2015-02-14 22:48:27 +00:00
# include "compiler-range_for.h"
# include "partial_range.h"
2006-03-20 17:12:09 +00:00
2008-10-28 17:58:54 +00:00
// Menu IDs...
enum MENUS
{
MENU_NEW_GAME = 0 ,
MENU_GAME ,
MENU_EDITOR ,
MENU_VIEW_SCORES ,
MENU_QUIT ,
MENU_LOAD_GAME ,
MENU_SAVE_GAME ,
MENU_DEMO_PLAY ,
MENU_CONFIG ,
MENU_REJOIN_NETGAME ,
MENU_DIFFICULTY ,
MENU_HELP ,
MENU_NEW_PLAYER ,
2011-09-13 23:15:32 +00:00
# if defined(USE_UDP)
2009-05-03 12:31:30 +00:00
MENU_MULTIPLAYER ,
# endif
2008-10-28 17:58:54 +00:00
MENU_SHOW_CREDITS ,
MENU_ORDER_INFO ,
2009-05-03 12:31:30 +00:00
2009-11-29 16:46:13 +00:00
# ifdef USE_UDP
2009-11-24 09:48:53 +00:00
MENU_START_UDP_NETGAME ,
MENU_JOIN_MANUAL_UDP_NETGAME ,
MENU_JOIN_LIST_UDP_NETGAME ,
2009-11-29 16:46:13 +00:00
# endif
2011-07-20 12:44:49 +00:00
# ifndef RELEASE
MENU_SANDBOX
# endif
2008-10-28 17:58:54 +00:00
} ;
2006-03-20 17:12:09 +00:00
//ADD_ITEM("Start netgame...", MENU_START_NETGAME, -1 );
//ADD_ITEM("Send net message...", MENU_SEND_NET_MESSAGE, -1 );
2015-01-18 01:58:31 +00:00
# define ADD_ITEM(t,value,key) do { nm_set_item_menu(m[num_options], t); menu_choice[num_options]=value;num_options++; } while (0)
2006-03-20 17:12:09 +00:00
2015-02-14 22:48:27 +00:00
static array < window * , 16 > menus ;
2010-03-18 02:49:02 +00:00
2006-03-20 17:12:09 +00:00
// Function Prototypes added after LINTING
2013-09-22 22:26:27 +00:00
static int do_option ( int select ) ;
static int do_new_game_menu ( void ) ;
static void do_multi_player_menu ( ) ;
2011-07-20 12:44:49 +00:00
# ifndef RELEASE
2013-09-22 22:26:27 +00:00
static void do_sandbox_menu ( ) ;
2011-07-20 12:44:49 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-01-29 04:05:47 +00:00
namespace {
2013-12-04 23:32:38 +00:00
template < typename T >
2016-01-29 04:05:47 +00:00
using select_file_subfunction = int ( * ) ( T * , const char * ) ;
}
2013-12-04 23:32:38 +00:00
2015-02-14 22:48:28 +00:00
__attribute_nonnull ( )
2016-03-06 18:11:20 +00:00
static int select_file_recursive2 ( const char * title , const char * orig_path , const partial_range_t < const file_extension_t * > & ext_list , int select_dir , select_file_subfunction < void > when_selected , void * userdata ) ;
2013-12-04 23:32:38 +00:00
2016-03-06 18:11:20 +00:00
template < typename T >
2015-02-14 22:48:28 +00:00
__attribute_nonnull ( )
2016-03-06 18:11:20 +00:00
static int select_file_recursive ( const char * title , const char * orig_path , const partial_range_t < const file_extension_t * > & ext_list , int select_dir , select_file_subfunction < T > when_selected , T * userdata )
2013-12-04 23:32:38 +00:00
{
2016-03-06 18:11:20 +00:00
return select_file_recursive2 ( title , orig_path , ext_list , select_dir , reinterpret_cast < select_file_subfunction < void > > ( when_selected ) , reinterpret_cast < void * > ( userdata ) ) ;
2013-12-04 23:32:38 +00:00
}
2013-11-26 22:19:52 +00:00
2010-03-18 02:49:02 +00:00
// Hide all menus
2010-03-30 03:47:51 +00:00
int hide_menus ( void )
2010-03-18 02:49:02 +00:00
{
window * wind ;
2010-03-27 08:00:53 +00:00
if ( menus [ 0 ] )
2010-03-30 03:47:51 +00:00
return 0 ; // there are already hidden menus
2010-03-27 03:24:14 +00:00
2015-02-14 22:48:27 +00:00
wind = window_get_front ( ) ;
range_for ( auto & i , partial_range ( menus , menus . size ( ) - 1 ) )
2010-03-18 02:49:02 +00:00
{
2015-02-14 22:48:27 +00:00
i = wind ;
if ( ! wind )
break ;
2015-01-17 18:31:41 +00:00
wind = window_set_visible ( * wind , 0 ) ;
2010-03-18 02:49:02 +00:00
}
2010-06-14 08:13:16 +00:00
2010-03-18 02:49:02 +00:00
Assert ( window_get_front ( ) = = NULL ) ;
2015-02-14 22:48:27 +00:00
menus . back ( ) = nullptr ;
2010-06-14 08:13:16 +00:00
2010-03-30 03:47:51 +00:00
return 1 ;
2010-03-18 02:49:02 +00:00
}
// Show all menus, with the front one shown first
// This makes sure EVENT_WINDOW_ACTIVATED is only sent to that window
void show_menus ( void )
{
2015-02-14 22:48:27 +00:00
range_for ( auto & i , menus )
{
if ( ! i )
break ;
if ( window_exists ( i ) )
window_set_visible ( i , 1 ) ;
}
2010-03-27 03:24:14 +00:00
menus [ 0 ] = NULL ;
2010-03-18 02:49:02 +00:00
}
2010-02-07 12:10:52 +00:00
//pairs of chars describing ranges
2016-07-16 16:52:04 +00:00
constexpr char playername_allowed_chars [ ] = " azAZ09__-- " ;
2010-02-07 12:10:52 +00:00
2013-10-27 22:00:14 +00:00
static int MakeNewPlayerFile ( int allow_abort )
2010-02-07 12:10:52 +00:00
{
int x ;
2011-06-06 19:19:38 +00:00
char filename [ PATH_MAX ] ;
2015-07-25 23:10:46 +00:00
callsign_t text = get_local_player ( ) . callsign ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
try_again :
2015-01-18 01:58:31 +00:00
{
2015-03-22 18:49:21 +00:00
array < newmenu_item , 1 > m { {
2015-01-18 01:58:31 +00:00
nm_item_input ( text . buffer ( ) ) ,
2015-03-22 18:49:21 +00:00
} } ;
2010-02-07 12:10:52 +00:00
Newmenu_allowed_chars = playername_allowed_chars ;
2015-01-18 01:58:32 +00:00
x = newmenu_do ( NULL , TXT_ENTER_PILOT_NAME , m , unused_newmenu_subfunction , unused_newmenu_userdata ) ;
2015-01-18 01:58:31 +00:00
}
2010-02-07 12:10:52 +00:00
Newmenu_allowed_chars = NULL ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
if ( x < 0 ) {
if ( allow_abort ) return 0 ;
goto try_again ;
}
2010-06-14 08:13:16 +00:00
2014-07-26 22:45:01 +00:00
if ( ! * static_cast < const char * > ( text ) ) //null string
2010-02-07 12:10:52 +00:00
goto try_again ;
2010-06-14 08:13:16 +00:00
2014-07-05 16:48:12 +00:00
text . lower ( ) ;
2010-06-14 08:13:16 +00:00
2014-07-05 16:48:12 +00:00
snprintf ( filename , sizeof ( filename ) , PLAYER_DIRECTORY_STRING ( " %s.plr " ) , static_cast < const char * > ( text ) ) ;
2010-06-14 08:13:16 +00:00
2011-06-01 07:59:55 +00:00
if ( PHYSFSX_exists ( filename , 0 ) )
2010-02-07 12:10:52 +00:00
{
2014-07-05 16:48:12 +00:00
nm_messagebox ( NULL , 1 , TXT_OK , " %s '%s' %s " , TXT_PLAYER , static_cast < const char * > ( text ) , TXT_ALREADY_EXISTS ) ;
2010-02-07 12:10:52 +00:00
goto try_again ;
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
if ( ! new_player_config ( ) )
goto try_again ; // They hit Esc during New player config
2010-06-14 08:13:16 +00:00
2015-07-25 23:10:46 +00:00
get_local_player ( ) . callsign = text ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
write_player_file ( ) ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
return 1 ;
}
2013-09-02 23:21:13 +00:00
static void delete_player_saved_games ( const char * name ) ;
2010-02-07 12:10:52 +00:00
2014-10-04 21:47:13 +00:00
static int player_menu_keycommand ( listbox * lb , const d_event & event )
2010-02-07 12:10:52 +00:00
{
2013-09-02 23:21:13 +00:00
const char * * items = listbox_get_items ( lb ) ;
2010-02-07 12:10:52 +00:00
int citem = listbox_get_citem ( lb ) ;
2010-06-14 08:13:16 +00:00
2011-01-14 09:51:13 +00:00
switch ( event_key_get ( event ) )
2010-02-07 12:10:52 +00:00
{
case KEY_CTRLED + KEY_D :
if ( citem > 0 )
{
int x = 1 ;
x = nm_messagebox ( NULL , 2 , TXT_YES , TXT_NO , " %s %s? " , TXT_DELETE_PILOT , items [ citem ] + ( ( items [ citem ] [ 0 ] = = ' $ ' ) ? 1 : 0 ) ) ;
if ( x = = 0 ) {
2011-04-22 15:14:29 +00:00
char plxfile [ PATH_MAX ] , efffile [ PATH_MAX ] , ngpfile [ PATH_MAX ] ;
2010-02-07 12:10:52 +00:00
int ret ;
char name [ PATH_MAX ] ;
2010-06-14 08:13:16 +00:00
2013-09-02 23:09:16 +00:00
snprintf ( name , sizeof ( name ) , PLAYER_DIRECTORY_STRING ( " %.8s.plr " ) , items [ citem ] ) ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
ret = ! PHYSFS_delete ( name ) ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
if ( ! ret )
{
delete_player_saved_games ( items [ citem ] ) ;
// delete PLX file
2013-10-06 21:04:29 +00:00
snprintf ( plxfile , sizeof ( plxfile ) , PLAYER_DIRECTORY_STRING ( " %.8s.plx " ) , items [ citem ] ) ;
2011-06-01 07:59:55 +00:00
if ( PHYSFSX_exists ( plxfile , 0 ) )
2010-02-07 12:10:52 +00:00
PHYSFS_delete ( plxfile ) ;
// delete EFF file
2013-10-06 21:04:29 +00:00
snprintf ( efffile , sizeof ( efffile ) , PLAYER_DIRECTORY_STRING ( " %.8s.eff " ) , items [ citem ] ) ;
2011-06-01 07:59:55 +00:00
if ( PHYSFSX_exists ( efffile , 0 ) )
2010-02-07 12:10:52 +00:00
PHYSFS_delete ( efffile ) ;
2011-04-22 15:14:29 +00:00
// delete NGP file
2013-10-06 21:04:29 +00:00
snprintf ( ngpfile , sizeof ( ngpfile ) , PLAYER_DIRECTORY_STRING ( " %.8s.ngp " ) , items [ citem ] ) ;
2011-06-01 07:59:55 +00:00
if ( PHYSFSX_exists ( ngpfile , 0 ) )
2011-04-22 15:14:29 +00:00
PHYSFS_delete ( ngpfile ) ;
2010-02-07 12:10:52 +00:00
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
if ( ret )
nm_messagebox ( NULL , 1 , TXT_OK , " %s %s %s " , TXT_COULDNT , TXT_DELETE_PILOT , items [ citem ] + ( ( items [ citem ] [ 0 ] = = ' $ ' ) ? 1 : 0 ) ) ;
else
listbox_delete_item ( lb , citem ) ;
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
return 1 ;
}
break ;
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
return 0 ;
}
2014-10-04 21:47:13 +00:00
static int player_menu_handler ( listbox * lb , const d_event & event , char * * list )
2010-02-07 12:10:52 +00:00
{
2013-09-02 23:21:13 +00:00
const char * * items = listbox_get_items ( lb ) ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-02-07 12:10:52 +00:00
{
case EVENT_KEY_COMMAND :
return player_menu_keycommand ( lb , event ) ;
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
2010-02-07 12:10:52 +00:00
if ( citem < 0 )
return 0 ; // shouldn't happen
else if ( citem = = 0 )
{
// They selected 'create new pilot'
return ! MakeNewPlayerFile ( 1 ) ;
}
else
{
2015-07-25 23:10:46 +00:00
get_local_player ( ) . callsign . copy_lower ( items [ citem ] , strlen ( items [ citem ] ) ) ;
2010-02-07 12:10:52 +00:00
}
break ;
2015-02-28 22:34:07 +00:00
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
case EVENT_WINDOW_CLOSE :
if ( read_player_file ( ) ! = EZERO )
return 1 ; // abort close!
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
WriteConfigFile ( ) ; // Update lastplr
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
PHYSFS_freeList ( list ) ;
d_free ( items ) ;
break ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
default :
break ;
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
return 0 ;
}
//Inputs the player's name, without putting up the background screen
int RegisterPlayer ( )
{
2015-03-22 18:49:21 +00:00
static const array < file_extension_t , 1 > types { { " plr " } } ;
2010-02-07 12:10:52 +00:00
int i = 0 , NumItems ;
int citem = 0 ;
int allow_abort_flag = 1 ;
2010-06-14 08:13:16 +00:00
2015-07-25 23:10:46 +00:00
if ( ! * static_cast < const char * > ( get_local_player ( ) . callsign ) )
2010-02-07 12:10:52 +00:00
{
2014-07-26 22:45:01 +00:00
if ( ! * static_cast < const char * > ( GameCfg . LastPlayer ) )
2010-06-23 12:57:28 +00:00
{
2015-07-25 23:10:46 +00:00
get_local_player ( ) . callsign = " player " ;
2010-02-07 12:10:52 +00:00
allow_abort_flag = 0 ;
2010-06-23 12:57:28 +00:00
}
else
{
// Read the last player's name from config file, not lastplr.txt
2015-07-25 23:10:46 +00:00
get_local_player ( ) . callsign = GameCfg . LastPlayer ;
2010-06-23 12:57:28 +00:00
}
2010-02-07 12:10:52 +00:00
}
2010-06-14 08:13:16 +00:00
2015-01-23 03:55:05 +00:00
auto list = PHYSFSX_findFiles ( PLAYER_DIRECTORY_STRING ( " " ) , types ) ;
2010-02-07 12:10:52 +00:00
if ( ! list )
return 0 ; // memory error
2015-01-23 03:55:05 +00:00
if ( ! list [ 0 ] )
2010-02-07 12:10:52 +00:00
{
MakeNewPlayerFile ( 0 ) ; // make a new player without showing listbox
return 0 ;
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
for ( NumItems = 0 ; list [ NumItems ] ! = NULL ; NumItems + + ) { }
NumItems + + ; // for TXT_CREATE_NEW
2010-06-14 08:13:16 +00:00
2015-07-18 21:01:55 +00:00
RAIIdmem < const char * [ ] > m ;
MALLOC ( m , const char * [ ] , NumItems ) ;
2010-02-07 12:10:52 +00:00
if ( m = = NULL )
{
return 0 ;
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
m [ i + + ] = TXT_CREATE_NEW ;
2010-06-14 08:13:16 +00:00
2015-07-18 21:01:55 +00:00
range_for ( const auto f , list )
2010-02-07 12:10:52 +00:00
{
char * p ;
2010-06-14 08:13:16 +00:00
2015-07-18 21:01:55 +00:00
size_t lenf = strlen ( f ) ;
2013-12-03 23:21:36 +00:00
if ( lenf > FILENAME_LEN - 1 | | lenf < 5 ) // sorry guys, can only have up to eight chars for the player name
2011-07-13 21:26:43 +00:00
{
NumItems - - ;
continue ;
}
2015-07-18 21:01:55 +00:00
m [ i + + ] = f ;
p = strchr ( f , ' . ' ) ;
2010-02-07 12:10:52 +00:00
if ( p )
* p = ' \0 ' ; // chop the .plr
2011-07-13 21:26:43 +00:00
}
if ( NumItems < = 1 ) // so it seems all plr files we found were too long. funny. let's make a real player
{
MakeNewPlayerFile ( 0 ) ; // make a new player without showing listbox
return 0 ;
2010-02-07 12:10:52 +00:00
}
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
// Sort by name, except the <Create New Player> string
2010-09-26 13:15:20 +00:00
qsort ( & m [ 1 ] , NumItems - 1 , sizeof ( char * ) , ( int ( * ) ( const void * , const void * ) ) string_array_sort_func ) ;
2010-02-07 12:10:52 +00:00
for ( i = 0 ; i < NumItems ; i + + )
2015-07-25 23:10:46 +00:00
if ( ! d_stricmp ( static_cast < const char * > ( get_local_player ( ) . callsign ) , m [ i ] ) )
2010-02-07 12:10:52 +00:00
citem = i ;
2015-07-18 21:01:55 +00:00
newmenu_listbox1 ( TXT_SELECT_PILOT , NumItems , m . release ( ) , allow_abort_flag , citem , player_menu_handler , list . release ( ) ) ;
2010-02-07 12:10:52 +00:00
return 1 ;
}
2010-04-03 10:16:53 +00:00
// Draw Copyright and Version strings
2013-10-27 22:00:14 +00:00
static void draw_copyright ( )
2010-04-03 10:16:53 +00:00
{
gr_set_current_canvas ( NULL ) ;
gr_set_curfont ( GAME_FONT ) ;
gr_set_fontcolor ( BM_XRGB ( 6 , 6 , 6 ) , - 1 ) ;
2015-06-13 22:42:22 +00:00
const auto & & line_spacing = LINE_SPACING ;
gr_string ( 0x8000 , SHEIGHT - line_spacing , TXT_COPYRIGHT ) ;
2010-04-03 10:16:53 +00:00
gr_set_fontcolor ( BM_XRGB ( 25 , 0 , 0 ) , - 1 ) ;
2015-06-13 22:42:22 +00:00
gr_string ( 0x8000 , SHEIGHT - ( line_spacing * 2 ) , DESCENT_VERSION ) ;
2010-04-03 10:16:53 +00:00
}
2016-03-19 19:08:10 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
// ------------------------------------------------------------------------
2014-10-04 21:47:13 +00:00
static int main_menu_handler ( newmenu * menu , const d_event & event , int * menu_choice )
2006-03-20 17:12:09 +00:00
{
2010-04-03 08:35:56 +00:00
newmenu_item * items = newmenu_get_items ( menu ) ;
2006-03-20 17:12:09 +00:00
2014-10-04 21:47:13 +00:00
switch ( event . type )
2008-01-13 13:27:58 +00:00
{
2010-01-27 09:11:47 +00:00
case EVENT_WINDOW_ACTIVATED :
2010-04-03 08:35:56 +00:00
load_palette ( MENU_PALETTE , 0 , 1 ) ; //get correct palette
2010-06-14 08:13:16 +00:00
2015-07-25 23:10:46 +00:00
if ( ! * static_cast < const char * > ( get_local_player ( ) . callsign ) )
2010-01-27 09:11:47 +00:00
RegisterPlayer ( ) ;
else
2010-12-10 23:18:17 +00:00
keyd_time_when_last_pressed = timer_query ( ) ; // .. 20 seconds from now!
2010-01-27 09:11:47 +00:00
break ;
2010-06-14 08:13:16 +00:00
2010-01-27 09:11:47 +00:00
case EVENT_KEY_COMMAND :
// Don't allow them to hit ESC in the main menu.
2011-01-14 09:51:13 +00:00
if ( event_key_get ( event ) = = KEY_ESC )
2010-01-30 03:24:19 +00:00
return 1 ;
2010-05-03 08:22:50 +00:00
break ;
2010-06-14 08:13:16 +00:00
2011-01-02 11:25:51 +00:00
case EVENT_MOUSE_BUTTON_DOWN :
case EVENT_MOUSE_BUTTON_UP :
// Don't allow mousebutton-closing in main menu.
2011-01-14 09:51:13 +00:00
if ( event_mouse_get_button ( event ) = = MBTN_RIGHT )
2011-01-02 11:25:51 +00:00
return 1 ;
break ;
2010-01-27 09:11:47 +00:00
case EVENT_IDLE :
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define DXX_DEMO_KEY_DELAY 45
# elif defined(DXX_BUILD_DESCENT_II)
2013-08-17 15:28:20 +00:00
# define DXX_DEMO_KEY_DELAY 25
2013-03-03 01:03:33 +00:00
# endif
2015-12-24 04:01:27 +00:00
if ( keyd_time_when_last_pressed + i2f ( DXX_DEMO_KEY_DELAY ) < timer_query ( ) | | CGameArg . SysAutoDemo )
2010-01-27 09:11:47 +00:00
{
2011-07-02 20:59:03 +00:00
keyd_time_when_last_pressed = timer_query ( ) ; // Reset timer so that disk won't thrash if no demos.
2010-06-14 08:13:16 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
int n_demos = newdemo_count_demos ( ) ;
2015-12-24 04:01:27 +00:00
if ( ( d_rand ( ) % ( n_demos + 1 ) ) = = 0 & & ! CGameArg . SysAutoDemo )
2010-01-27 09:11:47 +00:00
{
2006-03-20 17:12:09 +00:00
# ifdef OGL
2010-01-27 09:11:47 +00:00
Screen_mode = - 1 ;
2006-03-20 17:12:09 +00:00
# endif
2013-10-27 21:01:04 +00:00
PlayMovie ( " intro.tex " , " intro.mve " , 0 ) ;
2010-01-27 09:11:47 +00:00
songs_play_song ( SONG_TITLE , 1 ) ;
set_screen_mode ( SCREEN_MENU ) ;
}
else
2013-03-03 01:03:33 +00:00
# endif
2010-01-27 09:11:47 +00:00
{
newdemo_start_playback ( NULL ) ; // Randomly pick a file, assume native endian (crashes if not)
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2010-01-27 09:11:47 +00:00
if ( Newdemo_state = = ND_STATE_PLAYBACK )
2010-04-03 08:35:56 +00:00
return 0 ;
2013-03-03 01:03:33 +00:00
# endif
2010-01-27 09:11:47 +00:00
}
2006-03-20 17:12:09 +00:00
}
2010-01-27 09:11:47 +00:00
break ;
2010-06-14 08:13:16 +00:00
2010-04-03 10:16:53 +00:00
case EVENT_NEWMENU_DRAW :
draw_copyright ( ) ;
break ;
2010-06-14 08:13:16 +00:00
2010-04-03 08:35:56 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
return do_option ( menu_choice [ citem ] ) ;
}
2010-06-14 08:13:16 +00:00
2010-04-03 08:35:56 +00:00
case EVENT_WINDOW_CLOSE :
d_free ( menu_choice ) ;
d_free ( items ) ;
break ;
2010-06-14 08:13:16 +00:00
2010-01-27 09:11:47 +00:00
default :
break ;
2006-03-20 17:12:09 +00:00
}
2010-01-07 14:49:07 +00:00
2010-01-30 03:24:19 +00:00
return 0 ;
2006-03-20 17:12:09 +00:00
}
2009-05-03 12:31:30 +00:00
// -----------------------------------------------------------------------------
// Create the main menu.
2013-10-27 22:00:14 +00:00
static void create_main_menu ( newmenu_item * m , int * menu_choice , int * callers_num_options )
2006-03-20 17:12:09 +00:00
{
2014-01-07 20:58:47 +00:00
int num_options = 0 ;
2006-03-20 17:12:09 +00:00
# ifndef DEMO_ONLY
ADD_ITEM ( TXT_NEW_GAME , MENU_NEW_GAME , KEY_N ) ;
ADD_ITEM ( TXT_LOAD_GAME , MENU_LOAD_GAME , KEY_L ) ;
2011-09-13 23:15:32 +00:00
# if defined(USE_UDP)
2006-03-20 17:12:09 +00:00
ADD_ITEM ( TXT_MULTIPLAYER_ , MENU_MULTIPLAYER , - 1 ) ;
# endif
ADD_ITEM ( TXT_OPTIONS_ , MENU_CONFIG , - 1 ) ;
ADD_ITEM ( TXT_CHANGE_PILOTS , MENU_NEW_PLAYER , unused ) ;
ADD_ITEM ( TXT_VIEW_DEMO , MENU_DEMO_PLAY , 0 ) ;
ADD_ITEM ( TXT_VIEW_SCORES , MENU_VIEW_SCORES , KEY_V ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
if ( ! PHYSFSX_exists ( " warning.pcx " , 1 ) ) /* SHAREWARE */
# elif defined(DXX_BUILD_DESCENT_II)
2011-06-01 07:59:55 +00:00
if ( PHYSFSX_exists ( " orderd2.pcx " , 1 ) ) /* SHAREWARE */
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
ADD_ITEM ( TXT_ORDERING_INFO , MENU_ORDER_INFO , - 1 ) ;
ADD_ITEM ( TXT_CREDITS , MENU_SHOW_CREDITS , - 1 ) ;
# endif
ADD_ITEM ( TXT_QUIT , MENU_QUIT , KEY_Q ) ;
# ifndef RELEASE
2009-05-03 12:31:30 +00:00
if ( ! ( Game_mode & GM_MULTI ) ) {
2006-03-20 17:12:09 +00:00
# ifdef EDITOR
ADD_ITEM ( " Editor " , MENU_EDITOR , KEY_E ) ;
# endif
}
2011-07-20 12:44:49 +00:00
ADD_ITEM ( " SANDBOX " , MENU_SANDBOX , - 1 ) ;
2006-03-20 17:12:09 +00:00
# endif
* callers_num_options = num_options ;
}
//returns number of item chosen
2010-06-14 08:13:16 +00:00
int DoMenu ( )
2006-03-20 17:12:09 +00:00
{
2010-04-03 08:35:56 +00:00
int * menu_choice ;
newmenu_item * m ;
2006-03-20 17:12:09 +00:00
int num_options = 0 ;
2013-07-13 02:31:27 +00:00
CALLOC ( menu_choice , int , 25 ) ;
2010-04-03 08:35:56 +00:00
if ( ! menu_choice )
return - 1 ;
2013-07-13 02:31:27 +00:00
CALLOC ( m , newmenu_item , 25 ) ;
2010-04-03 08:35:56 +00:00
if ( ! m )
{
d_free ( menu_choice ) ;
return - 1 ;
}
2010-01-30 22:49:43 +00:00
2010-02-07 04:34:21 +00:00
create_main_menu ( m , menu_choice , & num_options ) ; // may have to change, eg, maybe selected pilot and no save games.
2013-12-04 22:45:33 +00:00
newmenu_do3 ( " " , NULL , num_options , m , main_menu_handler , menu_choice , 0 , Menu_pcx_name ) ;
2006-03-20 17:12:09 +00:00
2010-04-03 08:35:56 +00:00
return 0 ;
2006-03-20 17:12:09 +00:00
}
2016-03-19 19:08:10 +00:00
}
2006-03-20 17:12:09 +00:00
//returns flag, true means quit menu
2010-06-14 08:13:16 +00:00
int do_option ( int select )
2006-03-20 17:12:09 +00:00
{
switch ( select ) {
case MENU_NEW_GAME :
2010-03-18 07:02:38 +00:00
select_mission ( 0 , " New Game \n \n Select mission " , do_new_game_menu ) ;
2006-03-20 17:12:09 +00:00
break ;
case MENU_GAME :
break ;
case MENU_DEMO_PLAY :
2010-02-07 12:10:52 +00:00
select_demo ( ) ;
2006-03-20 17:12:09 +00:00
break ;
case MENU_LOAD_GAME :
2015-04-19 04:18:49 +00:00
state_restore_all ( 0 , secret_restore : : none , nullptr , blind_save : : no ) ;
2006-03-20 17:12:09 +00:00
break ;
# ifdef EDITOR
case MENU_EDITOR :
2012-04-17 09:37:15 +00:00
if ( ! Current_mission )
{
create_new_mine ( ) ;
SetPlayerFromCurseg ( ) ;
}
2010-06-14 08:13:16 +00:00
2010-04-03 08:35:56 +00:00
hide_menus ( ) ;
2012-03-19 05:49:19 +00:00
init_editor ( ) ;
2006-03-20 17:12:09 +00:00
break ;
# endif
case MENU_VIEW_SCORES :
2010-02-08 04:10:21 +00:00
scores_view ( NULL , - 1 ) ;
2006-03-20 17:12:09 +00:00
break ;
# if 1 //def SHAREWARE
case MENU_ORDER_INFO :
show_order_form ( ) ;
break ;
# endif
case MENU_QUIT :
# ifdef EDITOR
if ( ! SafetyCheck ( ) ) break ;
# endif
2010-04-03 08:35:56 +00:00
return 0 ;
2006-03-20 17:12:09 +00:00
case MENU_NEW_PLAYER :
2010-04-04 09:41:53 +00:00
RegisterPlayer ( ) ;
2006-03-20 17:12:09 +00:00
break ;
2009-11-29 16:46:13 +00:00
# ifdef USE_UDP
2009-11-24 09:48:53 +00:00
case MENU_START_UDP_NETGAME :
multi_protocol = MULTI_PROTO_UDP ;
2010-04-04 09:41:53 +00:00
select_mission ( 1 , TXT_MULTI_MISSION , net_udp_setup_game ) ;
2009-11-24 09:48:53 +00:00
break ;
case MENU_JOIN_MANUAL_UDP_NETGAME :
multi_protocol = MULTI_PROTO_UDP ;
net_udp_manual_join_game ( ) ;
break ;
case MENU_JOIN_LIST_UDP_NETGAME :
multi_protocol = MULTI_PROTO_UDP ;
2010-06-29 16:41:08 +00:00
net_udp_list_join_game ( ) ;
2009-11-24 09:48:53 +00:00
break ;
2009-11-29 16:46:13 +00:00
# endif
2011-09-13 23:15:32 +00:00
# if defined(USE_UDP)
2006-03-20 17:12:09 +00:00
case MENU_MULTIPLAYER :
do_multi_player_menu ( ) ;
break ;
2009-11-29 16:46:13 +00:00
# endif
2006-03-20 17:12:09 +00:00
case MENU_CONFIG :
do_options_menu ( ) ;
break ;
case MENU_SHOW_CREDITS :
2008-10-16 17:27:02 +00:00
credits_show ( NULL ) ;
2006-03-20 17:12:09 +00:00
break ;
2011-07-20 12:44:49 +00:00
# ifndef RELEASE
case MENU_SANDBOX :
do_sandbox_menu ( ) ;
break ;
# endif
2006-03-20 17:12:09 +00:00
default :
Error ( " Unknown option %d in do_option " , select ) ;
break ;
}
2010-04-03 08:35:56 +00:00
return 1 ; // stay in main menu unless quitting
2006-03-20 17:12:09 +00:00
}
2013-09-02 23:21:13 +00:00
static void delete_player_saved_games ( const char * name )
2009-12-08 11:01:36 +00:00
{
int i ;
2011-02-09 11:58:32 +00:00
char filename [ PATH_MAX ] ;
2010-06-14 08:13:16 +00:00
2009-12-08 11:01:36 +00:00
for ( i = 0 ; i < 10 ; i + + )
{
2013-10-06 21:04:29 +00:00
snprintf ( filename , sizeof ( filename ) , PLAYER_DIRECTORY_STRING ( " %s.sg%x " ) , name , i ) ;
2011-02-09 11:58:32 +00:00
PHYSFS_delete ( filename ) ;
2013-10-06 21:04:29 +00:00
snprintf ( filename , sizeof ( filename ) , PLAYER_DIRECTORY_STRING ( " %s.mg%x " ) , name , i ) ;
2009-12-08 11:01:36 +00:00
PHYSFS_delete ( filename ) ;
}
}
2014-10-04 21:47:13 +00:00
static int demo_menu_keycommand ( listbox * lb , const d_event & event )
2009-12-08 11:01:36 +00:00
{
2013-09-02 23:21:13 +00:00
const char * * items = listbox_get_items ( lb ) ;
2010-01-07 14:49:07 +00:00
int citem = listbox_get_citem ( lb ) ;
2010-06-14 08:13:16 +00:00
2011-01-14 09:51:13 +00:00
switch ( event_key_get ( event ) )
2009-12-08 11:01:36 +00:00
{
case KEY_CTRLED + KEY_D :
2010-02-07 12:10:52 +00:00
if ( citem > = 0 )
2009-12-08 11:01:36 +00:00
{
int x = 1 ;
2010-02-07 12:10:52 +00:00
x = nm_messagebox ( NULL , 2 , TXT_YES , TXT_NO , " %s %s? " , TXT_DELETE_DEMO , items [ citem ] + ( ( items [ citem ] [ 0 ] = = ' $ ' ) ? 1 : 0 ) ) ;
if ( x = = 0 )
{
2009-12-08 11:01:36 +00:00
int ret ;
char name [ PATH_MAX ] ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
strcpy ( name , DEMO_DIR ) ;
2010-01-07 14:49:07 +00:00
strcat ( name , items [ citem ] ) ;
2010-06-14 08:13:16 +00:00
2009-12-08 11:01:36 +00:00
ret = ! PHYSFS_delete ( name ) ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
if ( ret )
nm_messagebox ( NULL , 1 , TXT_OK , " %s %s %s " , TXT_COULDNT , TXT_DELETE_DEMO , items [ citem ] + ( ( items [ citem ] [ 0 ] = = ' $ ' ) ? 1 : 0 ) ) ;
2010-01-07 14:49:07 +00:00
else
listbox_delete_item ( lb , citem ) ;
2009-12-08 11:01:36 +00:00
}
2010-06-14 08:13:16 +00:00
2010-01-07 14:49:07 +00:00
return 1 ;
2009-12-08 11:01:36 +00:00
}
break ;
2010-06-14 08:13:16 +00:00
2010-02-07 12:10:52 +00:00
case KEY_CTRLED + KEY_C :
2009-12-08 11:01:36 +00:00
{
int x = 1 ;
char bakname [ PATH_MAX ] ;
2010-06-14 08:13:16 +00:00
2009-12-08 11:01:36 +00:00
// Get backup name
2010-02-07 12:10:52 +00:00
change_filename_extension ( bakname , items [ citem ] + ( ( items [ citem ] [ 0 ] = = ' $ ' ) ? 1 : 0 ) , DEMO_BACKUP_EXT ) ;
2009-12-08 11:01:36 +00:00
x = nm_messagebox ( NULL , 2 , TXT_YES , TXT_NO , " Are you sure you want to \n "
" swap the endianness of \n "
" %s? If the file is \n "
" already endian native, D1X \n "
" will likely crash. A backup \n "
2010-02-07 12:10:52 +00:00
" %s will be created " , items [ citem ] + ( ( items [ citem ] [ 0 ] = = ' $ ' ) ? 1 : 0 ) , bakname ) ;
2010-01-07 14:49:07 +00:00
if ( ! x )
newdemo_swap_endian ( items [ citem ] ) ;
2010-06-14 08:13:16 +00:00
2010-01-07 14:49:07 +00:00
return 1 ;
2009-12-08 11:01:36 +00:00
}
break ;
}
2010-06-14 08:13:16 +00:00
2010-02-06 05:21:45 +00:00
return 0 ;
}
2015-01-23 03:55:05 +00:00
static int demo_menu_handler ( listbox * lb , const d_event & event , char * * items )
2010-02-06 05:21:45 +00:00
{
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-02-06 05:21:45 +00:00
{
case EVENT_KEY_COMMAND :
2010-02-07 12:10:52 +00:00
return demo_menu_keycommand ( lb , event ) ;
2010-02-06 05:21:45 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
2010-02-06 05:21:45 +00:00
if ( citem < 0 )
return 0 ; // shouldn't happen
2010-02-07 12:10:52 +00:00
newdemo_start_playback ( items [ citem ] ) ;
2010-04-02 05:24:47 +00:00
return 1 ; // stay in demo selector
2015-02-28 22:34:07 +00:00
}
2010-02-06 05:21:45 +00:00
case EVENT_WINDOW_CLOSE :
2010-02-07 12:10:52 +00:00
PHYSFS_freeList ( items ) ;
2010-02-06 05:21:45 +00:00
break ;
default :
break ;
}
2010-01-07 14:49:07 +00:00
return 0 ;
2009-12-08 11:01:36 +00:00
}
2010-02-07 12:10:52 +00:00
int select_demo ( void )
2009-12-08 11:01:36 +00:00
{
2010-02-07 12:10:52 +00:00
int NumItems ;
2010-06-14 08:13:16 +00:00
2015-01-23 03:55:05 +00:00
auto list = PHYSFSX_findFiles ( DEMO_DIR , demo_file_extensions ) ;
2010-02-07 12:10:52 +00:00
if ( ! list )
2009-12-08 11:01:36 +00:00
return 0 ; // memory error
2015-01-23 03:55:05 +00:00
if ( ! list [ 0 ] )
2009-12-08 11:01:36 +00:00
{
nm_messagebox ( NULL , 1 , TXT_OK , " %s %s \n %s " , TXT_NO_DEMO_FILES , TXT_USE_F5 , TXT_TO_CREATE_ONE ) ;
return 0 ;
2010-06-14 08:13:16 +00:00
}
2010-02-07 12:10:52 +00:00
for ( NumItems = 0 ; list [ NumItems ] ! = NULL ; NumItems + + ) { }
2009-12-08 11:01:36 +00:00
2010-02-07 12:10:52 +00:00
// Sort by name
2015-01-23 03:55:05 +00:00
qsort ( list . get ( ) , NumItems , sizeof ( char * ) , ( int ( * ) ( const void * , const void * ) ) string_array_sort_func ) ;
2009-12-08 11:01:36 +00:00
2015-06-13 22:42:21 +00:00
auto clist = const_cast < const char * * > ( list . get ( ) ) ;
2015-01-23 03:55:05 +00:00
newmenu_listbox1 ( TXT_SELECT_DEMO , NumItems , clist , 1 , 0 , demo_menu_handler , list . release ( ) ) ;
2010-06-14 08:13:16 +00:00
2009-12-08 11:01:36 +00:00
return 1 ;
}
2013-10-27 22:00:14 +00:00
static int do_difficulty_menu ( )
2006-03-20 17:12:09 +00:00
{
int s ;
2015-03-22 18:49:21 +00:00
array < newmenu_item , NDL > m { {
2015-01-18 01:58:31 +00:00
nm_item_menu ( MENU_DIFFICULTY_TEXT ( 0 ) ) ,
nm_item_menu ( MENU_DIFFICULTY_TEXT ( 1 ) ) ,
nm_item_menu ( MENU_DIFFICULTY_TEXT ( 2 ) ) ,
nm_item_menu ( MENU_DIFFICULTY_TEXT ( 3 ) ) ,
nm_item_menu ( MENU_DIFFICULTY_TEXT ( 4 ) ) ,
2015-03-22 18:49:21 +00:00
} } ;
2006-03-20 17:12:09 +00:00
2015-01-18 01:58:31 +00:00
s = newmenu_do1 ( NULL , TXT_DIFFICULTY_LEVEL , m . size ( ) , & m . front ( ) , unused_newmenu_subfunction , unused_newmenu_userdata , Difficulty_level ) ;
2006-03-20 17:12:09 +00:00
2009-05-03 12:31:30 +00:00
if ( s > - 1 ) {
2006-03-20 17:12:09 +00:00
if ( s ! = Difficulty_level )
{
2008-04-13 00:28:36 +00:00
PlayerCfg . DefaultDifficulty = s ;
2006-03-20 17:12:09 +00:00
write_player_file ( ) ;
}
Difficulty_level = s ;
return 1 ;
}
return 0 ;
}
2010-03-18 07:02:38 +00:00
int do_new_game_menu ( )
2006-03-20 17:12:09 +00:00
{
int new_level_num , player_highest_level ;
new_level_num = 1 ;
2011-05-15 23:46:26 +00:00
# ifdef NDEBUG
2006-03-20 17:12:09 +00:00
player_highest_level = get_highest_level ( ) ;
if ( player_highest_level > Last_level )
2011-05-15 23:46:26 +00:00
# endif
2006-03-20 17:12:09 +00:00
player_highest_level = Last_level ;
if ( player_highest_level > 1 ) {
char info_text [ 80 ] ;
int choice ;
2011-05-15 23:46:26 +00:00
int valid = 0 ;
2006-03-20 17:12:09 +00:00
2013-08-28 03:12:41 +00:00
snprintf ( info_text , sizeof ( info_text ) , " %s %d " , TXT_START_ANY_LEVEL , player_highest_level ) ;
2011-05-15 23:46:26 +00:00
while ( ! valid )
{
2015-01-18 01:58:31 +00:00
array < char , 10 > num_text { " 1 " } ;
2015-03-22 18:49:21 +00:00
array < newmenu_item , 2 > m { {
2015-01-18 01:58:31 +00:00
nm_item_text ( info_text ) ,
nm_item_input ( num_text ) ,
2015-03-22 18:49:21 +00:00
} } ;
2015-01-18 01:58:32 +00:00
choice = newmenu_do ( NULL , TXT_SELECT_START_LEV , m , unused_newmenu_subfunction , unused_newmenu_userdata ) ;
2006-03-20 17:12:09 +00:00
2011-05-15 23:46:26 +00:00
if ( choice = = - 1 | | m [ 1 ] . text [ 0 ] = = 0 )
return 0 ;
2006-03-20 17:12:09 +00:00
2011-05-15 23:46:26 +00:00
new_level_num = atoi ( m [ 1 ] . text ) ;
2006-03-20 17:12:09 +00:00
2011-05-15 23:46:26 +00:00
if ( ! ( new_level_num > 0 & & new_level_num < = player_highest_level ) ) {
nm_messagebox ( NULL , 1 , TXT_OK , TXT_INVALID_LEVEL ) ;
valid = 0 ;
}
else
valid = 1 ;
2006-03-20 17:12:09 +00:00
}
}
2007-09-28 22:44:04 +00:00
2008-04-13 00:28:36 +00:00
Difficulty_level = PlayerCfg . DefaultDifficulty ;
2006-03-20 17:12:09 +00:00
if ( ! do_difficulty_menu ( ) )
2010-03-18 07:02:38 +00:00
return 0 ;
2006-03-20 17:12:09 +00:00
StartNewGame ( new_level_num ) ;
2010-03-18 07:02:38 +00:00
return 1 ; // exit mission listbox
}
2013-09-22 22:26:27 +00:00
static void do_sound_menu ( ) ;
static void input_config ( ) ;
static void change_res ( ) ;
2015-09-26 17:48:57 +00:00
static void hud_config ( ) ;
2013-09-22 22:26:27 +00:00
static void graphics_config ( ) ;
2015-09-26 17:48:57 +00:00
static void gameplay_config ( ) ;
2010-01-17 14:42:59 +00:00
2015-03-07 17:20:40 +00:00
# define DXX_OPTIONS_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , MENU , " Sound & music... " , sfx ) \
DXX_MENUITEM ( VERB , MENU , TXT_CONTROLS_ , controls ) \
DXX_MENUITEM ( VERB , MENU , " Graphics... " , graphics ) \
DXX_MENUITEM ( VERB , MENU , " Gameplay... " , misc ) \
2015-03-07 17:20:40 +00:00
namespace {
class options_menu_items
{
public :
enum
{
DXX_OPTIONS_MENU ( ENUM )
} ;
array < newmenu_item , DXX_OPTIONS_MENU ( COUNT ) > m ;
options_menu_items ( )
{
DXX_OPTIONS_MENU ( ADD ) ;
}
} ;
}
2015-04-26 20:15:56 +00:00
static int options_menuset ( newmenu * , const d_event & event , options_menu_items * items )
2006-03-20 17:12:09 +00:00
{
2014-10-04 21:47:13 +00:00
switch ( event . type )
2006-03-20 17:12:09 +00:00
{
2010-02-01 06:55:38 +00:00
case EVENT_NEWMENU_CHANGED :
2010-01-17 14:42:59 +00:00
break ;
2010-06-14 08:13:16 +00:00
2010-01-17 14:42:59 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
switch ( citem )
2010-01-17 14:42:59 +00:00
{
2015-03-07 17:20:40 +00:00
case options_menu_items : : sfx :
do_sound_menu ( ) ;
break ;
case options_menu_items : : controls :
input_config ( ) ;
break ;
case options_menu_items : : graphics :
graphics_config ( ) ;
break ;
case options_menu_items : : misc :
2015-09-26 17:48:57 +00:00
gameplay_config ( ) ;
2015-03-07 17:20:40 +00:00
break ;
2010-01-17 14:42:59 +00:00
}
2010-01-30 03:24:19 +00:00
return 1 ; // stay in menu until escape
2015-02-28 22:34:07 +00:00
}
2010-06-14 08:13:16 +00:00
2010-01-20 05:10:32 +00:00
case EVENT_WINDOW_CLOSE :
2010-04-04 09:41:53 +00:00
{
2015-03-07 17:20:40 +00:00
std : : default_delete < options_menu_items > ( ) ( items ) ;
2010-01-17 14:42:59 +00:00
write_player_file ( ) ;
break ;
2010-04-04 09:41:53 +00:00
}
2010-06-14 08:13:16 +00:00
2010-01-30 03:24:19 +00:00
default :
break ;
2006-03-20 17:12:09 +00:00
}
2010-01-30 03:24:19 +00:00
return 0 ;
2006-03-20 17:12:09 +00:00
}
2013-10-27 22:00:14 +00:00
static int gcd ( int a , int b )
2006-03-20 17:12:09 +00:00
{
2008-10-19 12:53:30 +00:00
if ( ! b )
2010-06-14 08:13:16 +00:00
return a ;
2008-10-19 12:53:30 +00:00
return gcd ( b , a % b ) ;
2006-03-20 17:12:09 +00:00
}
void change_res ( )
{
2015-05-14 02:23:13 +00:00
array < screen_mode , 50 > modes ;
2016-02-12 04:02:28 +00:00
int mc = 0 , citem = - 1 ;
2010-06-24 09:29:11 +00:00
2015-05-14 02:23:13 +00:00
const auto num_presets = gr_list_modes ( modes ) ;
2010-06-24 09:29:11 +00:00
2010-10-10 10:48:24 +00:00
newmenu_item m [ 50 + 8 ] ;
char restext [ 50 ] [ 12 ] , crestext [ 12 ] , casptext [ 12 ] ;
2010-06-24 09:29:11 +00:00
2016-02-12 04:02:28 +00:00
range_for ( auto & i , partial_const_range ( modes , num_presets ) )
2010-06-24 09:29:11 +00:00
{
2016-07-31 22:25:50 +00:00
const auto & & sm_w = SM_W ( i ) ;
const auto & & sm_h = SM_H ( i ) ;
snprintf ( restext [ mc ] , sizeof ( restext [ mc ] ) , " %ix%i " , sm_w , sm_h ) ;
const auto checked = ( citem = = - 1 & & Game_screen_mode = = i & & GameCfg . AspectY = = sm_w / gcd ( sm_w , sm_h ) & & GameCfg . AspectX = = sm_h / gcd ( sm_w , sm_h ) ) ;
if ( checked )
2010-06-24 09:29:11 +00:00
citem = mc ;
2016-07-31 22:25:50 +00:00
nm_set_item_radio ( m [ mc ] , restext [ mc ] , checked , 0 ) ;
2010-06-24 09:29:11 +00:00
mc + + ;
}
2008-10-19 12:53:30 +00:00
2015-01-18 01:58:31 +00:00
nm_set_item_text ( m [ mc ] , " " ) ; mc + + ; // little space for overview
2010-06-24 09:29:11 +00:00
// the fields for custom resolution and aspect
2015-05-14 02:23:13 +00:00
const auto opt_cval = mc ;
2015-01-18 01:58:31 +00:00
nm_set_item_radio ( m [ mc ] , " use custom values " , ( citem = = - 1 ) , 0 ) ; mc + + ;
2015-01-18 01:58:31 +00:00
nm_set_item_text ( m [ mc ] , " resolution: " ) ; mc + + ;
2010-06-24 09:29:11 +00:00
snprintf ( crestext , sizeof ( crestext ) , " %ix%i " , SM_W ( Game_screen_mode ) , SM_H ( Game_screen_mode ) ) ;
2015-01-18 01:58:31 +00:00
nm_set_item_input ( m [ mc ] , crestext ) ;
2015-05-14 02:23:13 +00:00
mc + + ;
2015-01-18 01:58:31 +00:00
nm_set_item_text ( m [ mc ] , " aspect: " ) ; mc + + ;
2010-06-24 09:29:11 +00:00
snprintf ( casptext , sizeof ( casptext ) , " %ix%i " , GameCfg . AspectY , GameCfg . AspectX ) ;
2015-01-18 01:58:31 +00:00
nm_set_item_input ( m [ mc ] , casptext ) ;
2015-05-14 02:23:13 +00:00
mc + + ;
2015-01-18 01:58:31 +00:00
nm_set_item_text ( m [ mc ] , " " ) ; mc + + ; // little space for overview
2010-06-24 09:29:11 +00:00
// fullscreen
2015-05-14 02:23:13 +00:00
const auto opt_fullscr = mc ;
2015-01-18 01:58:31 +00:00
nm_set_item_checkbox ( m [ mc ] , " Fullscreen " , gr_check_fullscreen ( ) ) ;
mc + + ;
2008-04-06 20:23:28 +00:00
2008-10-19 12:53:30 +00:00
// create the menu
2013-12-04 22:45:33 +00:00
newmenu_do1 ( NULL , " Screen Resolution " , mc , m , unused_newmenu_subfunction , unused_newmenu_userdata , 0 ) ;
2008-10-19 12:53:30 +00:00
// menu is done, now do what we need to do
2006-08-30 18:12:04 +00:00
2010-06-24 09:29:11 +00:00
// check which resolution field was selected
2016-02-12 04:02:28 +00:00
unsigned i ;
2010-06-24 09:29:11 +00:00
for ( i = 0 ; i < = mc ; i + + )
2016-07-31 22:25:50 +00:00
if ( m [ i ] . type = = NM_TYPE_RADIO & & m [ i ] . radio ( ) . group = = 0 & & m [ i ] . value = = 1 )
2010-06-24 09:29:11 +00:00
break ;
2008-10-19 12:53:30 +00:00
// now check for fullscreen toggle and apply if necessary
2010-06-24 09:29:11 +00:00
if ( m [ opt_fullscr ] . value ! = gr_check_fullscreen ( ) )
2006-03-20 17:12:09 +00:00
gr_toggle_fullscreen ( ) ;
2015-05-14 02:23:13 +00:00
screen_mode new_mode ;
2010-06-24 09:29:11 +00:00
if ( i = = opt_cval ) // set custom resolution and aspect
2006-03-20 17:12:09 +00:00
{
2015-03-22 18:49:21 +00:00
char * x ;
unsigned long w = strtoul ( crestext , & x , 10 ) , h ;
2015-05-14 02:23:13 +00:00
screen_mode cmode ;
2015-03-22 18:49:21 +00:00
if ( * x ! = ' x ' | | ( ( h = strtoul ( x + 1 , & x , 10 ) ) , * x ) )
{
nm_messagebox ( TXT_WARNING , 1 , " OK " , " Entered resolution is bad. \n Reverting ... " ) ;
2015-05-14 02:23:13 +00:00
cmode = { } ;
2015-03-22 18:49:21 +00:00
}
else if ( w < 320 | | h < 200 )
2008-10-19 12:53:30 +00:00
{
2015-03-22 18:49:21 +00:00
// oh oh - the resolution is too small. Revert!
2008-10-19 12:53:30 +00:00
nm_messagebox ( TXT_WARNING , 1 , " OK " , " Entered resolution is too small. \n Reverting ... " ) ;
2015-05-14 02:23:13 +00:00
cmode = { } ;
2008-10-19 12:53:30 +00:00
}
2015-03-22 18:49:21 +00:00
else
{
2015-05-14 02:23:13 +00:00
cmode . width = w ;
cmode . height = h ;
2015-03-22 18:49:21 +00:00
}
auto casp = cmode ;
2015-03-22 18:49:21 +00:00
w = strtoul ( casptext , & x , 10 ) ;
if ( * x ! = ' x ' | | ( ( h = strtoul ( x + 1 , & x , 10 ) ) , * x ) )
{
nm_messagebox ( TXT_WARNING , 1 , " OK " , " Aspect resolution is bad. \n Ignoring ... " ) ;
}
else
2008-10-19 12:53:30 +00:00
{
2015-03-22 18:49:21 +00:00
// we even have a custom aspect set up
2015-05-14 02:23:13 +00:00
casp . width = w ;
casp . height = h ;
2008-10-19 12:53:30 +00:00
}
2015-05-14 02:23:13 +00:00
const auto g = gcd ( SM_W ( casp ) , SM_H ( casp ) ) ;
GameCfg . AspectY = SM_W ( casp ) / g ;
GameCfg . AspectX = SM_H ( casp ) / g ;
2010-06-24 09:29:11 +00:00
new_mode = cmode ;
2006-03-20 17:12:09 +00:00
}
2016-02-12 04:02:28 +00:00
else if ( i < num_presets ) // set preset resolution
2006-03-20 17:12:09 +00:00
{
2010-06-24 09:29:11 +00:00
new_mode = modes [ i ] ;
2015-05-14 02:23:13 +00:00
const auto g = gcd ( SM_W ( new_mode ) , SM_H ( new_mode ) ) ;
GameCfg . AspectY = SM_W ( new_mode ) / g ;
GameCfg . AspectX = SM_H ( new_mode ) / g ;
2006-03-20 17:12:09 +00:00
}
2008-10-19 12:53:30 +00:00
// clean up and apply everything
2010-07-31 12:09:38 +00:00
newmenu_free_background ( ) ;
2007-07-26 23:57:29 +00:00
set_screen_mode ( SCREEN_MENU ) ;
2010-06-24 09:29:11 +00:00
if ( new_mode ! = Game_screen_mode )
2011-01-16 01:09:47 +00:00
{
2010-06-24 09:29:11 +00:00
gr_set_mode ( new_mode ) ;
2011-01-16 01:09:47 +00:00
Game_screen_mode = new_mode ;
if ( Game_wind ) // shortly activate Game_wind so it's canvas will align to new resolution. really minor glitch but whatever
{
d_event event ;
WINDOW_SEND_EVENT ( Game_wind , EVENT_WINDOW_ACTIVATED ) ;
WINDOW_SEND_EVENT ( Game_wind , EVENT_WINDOW_DEACTIVATED ) ;
}
}
2012-05-26 22:24:57 +00:00
game_init_render_buffers ( SM_W ( Game_screen_mode ) , SM_H ( Game_screen_mode ) ) ;
2006-03-20 17:12:09 +00:00
}
2015-09-25 21:59:20 +00:00
static void input_config_keyboard ( )
2010-12-28 18:11:10 +00:00
{
2015-05-14 02:23:13 +00:00
# define DXX_INPUT_SENSITIVITY(VERB,OPT,VAL) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , SLIDER , TXT_TURN_LR , opt_ # # OPT # # _turn_lr , VAL [ 0 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_PITCH_UD , opt_ # # OPT # # _pitch_ud , VAL [ 1 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_SLIDE_LR , opt_ # # OPT # # _slide_lr , VAL [ 2 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_SLIDE_UD , opt_ # # OPT # # _slide_ud , VAL [ 3 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_BANK_LR , opt_ # # OPT # # _bank_lr , VAL [ 4 ] , 0 , 16 ) \
2015-05-14 02:23:13 +00:00
2015-09-25 21:59:20 +00:00
# define DXX_INPUT_CONFIG_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " Keyboard Sensitivity: " , opt_label_kb ) \
2015-09-25 21:59:20 +00:00
DXX_INPUT_SENSITIVITY ( VERB , kb , PlayerCfg . KeyboardSens ) \
class menu_items
{
public :
enum
{
DXX_INPUT_CONFIG_MENU ( ENUM )
} ;
array < newmenu_item , DXX_INPUT_CONFIG_MENU ( COUNT ) > m ;
menu_items ( )
{
DXX_INPUT_CONFIG_MENU ( ADD ) ;
}
} ;
# undef DXX_INPUT_CONFIG_MENU
menu_items items ;
newmenu_do1 ( nullptr , " Keyboard Calibration " , items . m . size ( ) , items . m . data ( ) , unused_newmenu_subfunction , unused_newmenu_userdata , 1 ) ;
constexpr uint_fast32_t keysens = items . opt_label_kb + 1 ;
const auto & m = items . m ;
2015-10-03 17:17:49 +00:00
for ( unsigned i = 0 ; i < 5 ; i + + )
2015-09-25 21:59:20 +00:00
{
2015-10-03 17:17:49 +00:00
PlayerCfg . KeyboardSens [ i ] = m [ keysens + i ] . value ;
2015-09-25 21:59:20 +00:00
}
}
static void input_config_mouse ( )
{
# define DXX_INPUT_SENSITIVITY(VERB,OPT,VAL) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , SLIDER , TXT_TURN_LR , opt_ # # OPT # # _turn_lr , VAL [ 0 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_PITCH_UD , opt_ # # OPT # # _pitch_ud , VAL [ 1 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_SLIDE_LR , opt_ # # OPT # # _slide_lr , VAL [ 2 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_SLIDE_UD , opt_ # # OPT # # _slide_ud , VAL [ 3 ] , 0 , 16 ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_BANK_LR , opt_ # # OPT # # _bank_lr , VAL [ 4 ] , 0 , 16 ) \
2015-09-25 21:59:20 +00:00
2015-05-14 02:23:13 +00:00
# define DXX_INPUT_THROTTLE_SENSITIVITY(VERB,OPT,VAL) \
DXX_INPUT_SENSITIVITY ( VERB , OPT , VAL ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , SLIDER , TXT_THROTTLE , opt_ # # OPT # # _throttle , VAL [ 5 ] , 0 , 16 ) \
2015-05-14 02:23:13 +00:00
2015-09-25 21:59:20 +00:00
# define DXX_INPUT_CONFIG_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " Mouse Sensitivity: " , opt_label_ms ) \
2015-09-25 21:59:20 +00:00
DXX_INPUT_THROTTLE_SENSITIVITY ( VERB , ms , PlayerCfg . MouseSens ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_ms ) \
DXX_MENUITEM ( VERB , TEXT , " Mouse Overrun Buffer: " , opt_label_mo ) \
2015-09-25 21:59:20 +00:00
DXX_INPUT_THROTTLE_SENSITIVITY ( VERB , mo , PlayerCfg . MouseOverrun ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_mo ) \
DXX_MENUITEM ( VERB , TEXT , " Mouse FlightSim Deadzone: " , opt_label_mfsd ) \
DXX_MENUITEM ( VERB , SLIDER , " X/Y " , opt_mfsd_deadzone , PlayerCfg . MouseFSDead , 0 , 16 ) \
2015-09-25 21:59:20 +00:00
class menu_items
{
public :
enum
{
DXX_INPUT_CONFIG_MENU ( ENUM )
} ;
array < newmenu_item , DXX_INPUT_CONFIG_MENU ( COUNT ) > m ;
menu_items ( )
{
DXX_INPUT_CONFIG_MENU ( ADD ) ;
}
} ;
# undef DXX_INPUT_CONFIG_MENU
menu_items items ;
newmenu_do1 ( nullptr , " Mouse Calibration " , items . m . size ( ) , items . m . data ( ) , unused_newmenu_subfunction , unused_newmenu_userdata , 1 ) ;
constexpr uint_fast32_t mousesens = items . opt_label_ms + 1 ;
constexpr uint_fast32_t mouseoverrun = items . opt_label_mo + 1 ;
const auto & m = items . m ;
for ( unsigned i = 0 ; i < = 5 ; i + + )
{
PlayerCfg . MouseSens [ i ] = m [ mousesens + i ] . value ;
PlayerCfg . MouseOverrun [ i ] = m [ mouseoverrun + i ] . value ;
}
constexpr uint_fast32_t mousefsdead = items . opt_mfsd_deadzone ;
PlayerCfg . MouseFSDead = m [ mousefsdead ] . value ;
}
2015-11-01 21:15:40 +00:00
# if MAX_AXES_PER_JOYSTICK
2015-09-25 21:59:20 +00:00
static void input_config_joystick ( )
{
# define DXX_INPUT_CONFIG_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " Joystick Sensitivity: " , opt_label_js ) \
2015-05-14 02:23:13 +00:00
DXX_INPUT_THROTTLE_SENSITIVITY ( VERB , js , PlayerCfg . JoystickSens ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_js ) \
DXX_MENUITEM ( VERB , TEXT , " Joystick Linearity: " , opt_label_jl ) \
2015-06-09 23:42:50 +00:00
DXX_INPUT_THROTTLE_SENSITIVITY ( VERB , jl , PlayerCfg . JoystickLinear ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_jl ) \
DXX_MENUITEM ( VERB , TEXT , " Joystick Linear Speed: " , opt_label_jp ) \
2015-06-09 23:42:50 +00:00
DXX_INPUT_THROTTLE_SENSITIVITY ( VERB , jp , PlayerCfg . JoystickSpeed ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_jp ) \
DXX_MENUITEM ( VERB , TEXT , " Joystick Deadzone: " , opt_label_jd ) \
2015-09-25 21:59:20 +00:00
DXX_INPUT_THROTTLE_SENSITIVITY ( VERB , jd , PlayerCfg . JoystickDead ) \
2015-05-14 02:23:13 +00:00
class menu_items
{
public :
enum
{
DXX_INPUT_CONFIG_MENU ( ENUM )
} ;
array < newmenu_item , DXX_INPUT_CONFIG_MENU ( COUNT ) > m ;
menu_items ( )
{
DXX_INPUT_CONFIG_MENU ( ADD ) ;
}
} ;
# undef DXX_INPUT_CONFIG_MENU
# undef DXX_INPUT_THROTTLE_SENSITIVITY
# undef DXX_INPUT_SENSITIVITY
menu_items items ;
2015-09-25 21:59:20 +00:00
newmenu_do1 ( nullptr , " Joystick Calibration " , items . m . size ( ) , items . m . data ( ) , unused_newmenu_subfunction , unused_newmenu_userdata , 1 ) ;
2015-05-14 02:23:13 +00:00
constexpr uint_fast32_t joysens = items . opt_label_js + 1 ;
2015-06-09 23:42:50 +00:00
constexpr uint_fast32_t joylin = items . opt_label_jl + 1 ;
constexpr uint_fast32_t joyspd = items . opt_label_jp + 1 ;
2015-05-14 02:23:13 +00:00
constexpr uint_fast32_t joydead = items . opt_label_jd + 1 ;
const auto & m = items . m ;
for ( unsigned i = 0 ; i < = 5 ; i + + )
2010-12-28 18:11:10 +00:00
{
2015-06-09 23:42:50 +00:00
PlayerCfg . JoystickLinear [ i ] = m [ joylin + i ] . value ;
PlayerCfg . JoystickSpeed [ i ] = m [ joyspd + i ] . value ;
2010-12-28 18:11:10 +00:00
PlayerCfg . JoystickSens [ i ] = m [ joysens + i ] . value ;
PlayerCfg . JoystickDead [ i ] = m [ joydead + i ] . value ;
}
}
2015-11-01 21:15:40 +00:00
# endif
2010-12-28 18:11:10 +00:00
2015-05-14 02:23:13 +00:00
namespace {
class input_config_menu_items
2008-02-24 14:41:27 +00:00
{
2015-11-01 21:15:40 +00:00
# if MAX_JOYSTICKS
# define DXX_INPUT_CONFIG_JOYSTICK_ITEM(I) I
# else
# define DXX_INPUT_CONFIG_JOYSTICK_ITEM(I)
# endif
# if MAX_AXES_PER_JOYSTICK
# define DXX_INPUT_CONFIG_JOYSTICK_AXIS_ITEM(I) I
# else
# define DXX_INPUT_CONFIG_JOYSTICK_AXIS_ITEM(I)
# endif
2015-05-14 02:23:13 +00:00
# define DXX_INPUT_CONFIG_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_INPUT_CONFIG_JOYSTICK_ITEM ( DXX_MENUITEM ( VERB , CHECK , " Use joystick " , opt_ic_usejoy , PlayerCfg . ControlType & CONTROL_USING_JOYSTICK ) ) \
DXX_MENUITEM ( VERB , CHECK , " Use mouse " , opt_ic_usemouse , PlayerCfg . ControlType & CONTROL_USING_MOUSE ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_use ) \
DXX_MENUITEM ( VERB , MENU , TXT_CUST_KEYBOARD , opt_ic_confkey ) \
DXX_INPUT_CONFIG_JOYSTICK_ITEM ( DXX_MENUITEM ( VERB , MENU , " Customize Joystick " , opt_ic_confjoy ) ) \
DXX_MENUITEM ( VERB , MENU , " Customize Mouse " , opt_ic_confmouse ) \
DXX_MENUITEM ( VERB , MENU , " Customize Weapon Keys " , opt_ic_confweap ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_customize ) \
DXX_MENUITEM ( VERB , TEXT , " Mouse Control Type: " , opt_label_mouse_control_type ) \
DXX_MENUITEM ( VERB , RADIO , " Normal " , opt_mouse_control_normal , PlayerCfg . MouseFlightSim = = 0 , optgrp_mouse_control_type ) \
DXX_MENUITEM ( VERB , RADIO , " FlightSim " , opt_mouse_control_flightsim , PlayerCfg . MouseFlightSim = = 1 , optgrp_mouse_control_type ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_mouse_control_type ) \
DXX_MENUITEM ( VERB , MENU , " Keyboard Calibration " , opt_ic_keyboard ) \
DXX_MENUITEM ( VERB , MENU , " Mouse Calibration " , opt_ic_mouse ) \
DXX_INPUT_CONFIG_JOYSTICK_AXIS_ITEM ( DXX_MENUITEM ( VERB , MENU , " Joystick Calibration " , opt_ic_joystick ) ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_sensitivity_deadzone ) \
DXX_MENUITEM ( VERB , CHECK , " Keep Keyboard/Mouse focus " , opt_ic_grabinput , CGameCfg . Grabinput ) \
DXX_MENUITEM ( VERB , CHECK , " Mouse FlightSim Indicator " , opt_ic_mousefsgauge , PlayerCfg . MouseFSIndicator ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_focus ) \
DXX_MENUITEM ( VERB , TEXT , " When dead, respawn by pressing: " , opt_label_respawn_mode ) \
DXX_MENUITEM ( VERB , RADIO , " Any key " , opt_respawn_any_key , PlayerCfg . RespawnMode = = RespawnPress : : Any , optgrp_respawn_mode ) \
DXX_MENUITEM ( VERB , RADIO , " Fire keys (pri., sec., flare) " , opt_respawn_fire_key , PlayerCfg . RespawnMode = = RespawnPress : : Fire , optgrp_respawn_mode ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_respawn ) \
DXX_MENUITEM ( VERB , MENU , " GAME SYSTEM KEYS " , opt_ic_help0 ) \
DXX_MENUITEM ( VERB , MENU , " NETGAME SYSTEM KEYS " , opt_ic_help1 ) \
DXX_MENUITEM ( VERB , MENU , " DEMO SYSTEM KEYS " , opt_ic_help2 ) \
2015-05-14 02:23:13 +00:00
public :
enum
{
optgrp_mouse_control_type ,
2015-11-21 18:12:13 +00:00
optgrp_respawn_mode ,
2015-05-14 02:23:13 +00:00
} ;
enum
{
DXX_INPUT_CONFIG_MENU ( ENUM )
} ;
array < newmenu_item , DXX_INPUT_CONFIG_MENU ( COUNT ) > m ;
input_config_menu_items ( )
{
DXX_INPUT_CONFIG_MENU ( ADD ) ;
}
static int menuset ( newmenu * , const d_event & event , input_config_menu_items * pitems ) ;
# undef DXX_INPUT_CONFIG_MENU
2015-11-01 21:15:40 +00:00
# undef DXX_INPUT_CONFIG_JOYSTICK_AXIS_ITEM
# undef DXX_INPUT_CONFIG_JOYSTICK_ITEM
2015-05-14 02:23:13 +00:00
} ;
}
int input_config_menu_items : : menuset ( newmenu * , const d_event & event , input_config_menu_items * pitems )
{
const auto & items = pitems - > m ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-01-17 14:42:59 +00:00
{
2010-02-01 06:55:38 +00:00
case EVENT_NEWMENU_CHANGED :
2015-02-28 22:34:07 +00:00
{
2015-05-14 02:23:13 +00:00
const auto citem = static_cast < const d_change_event & > ( event ) . citem ;
2015-11-01 21:15:40 +00:00
# if MAX_JOYSTICKS
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_usejoy )
2015-05-09 17:39:02 +00:00
{
constexpr auto flag = CONTROL_USING_JOYSTICK ;
if ( items [ citem ] . value )
PlayerCfg . ControlType | = flag ;
else
PlayerCfg . ControlType & = ~ flag ;
}
2015-11-01 21:15:40 +00:00
# endif
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_usemouse )
2015-05-09 17:39:02 +00:00
{
constexpr auto flag = CONTROL_USING_MOUSE ;
if ( items [ citem ] . value )
PlayerCfg . ControlType | = flag ;
else
PlayerCfg . ControlType & = ~ flag ;
}
2015-05-14 02:23:13 +00:00
if ( citem = = opt_mouse_control_normal )
2011-01-04 10:43:37 +00:00
PlayerCfg . MouseFlightSim = 0 ;
2015-05-14 02:23:13 +00:00
if ( citem = = opt_mouse_control_flightsim )
2011-01-04 10:43:37 +00:00
PlayerCfg . MouseFlightSim = 1 ;
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_grabinput )
2015-07-18 21:01:56 +00:00
CGameCfg . Grabinput = items [ citem ] . value ;
2011-01-04 10:43:37 +00:00
if ( citem = = opt_ic_mousefsgauge )
2011-01-10 15:12:04 +00:00
PlayerCfg . MouseFSIndicator = items [ citem ] . value ;
2015-11-21 18:12:13 +00:00
else if ( citem = = opt_respawn_any_key )
PlayerCfg . RespawnMode = RespawnPress : : Any ;
else if ( citem = = opt_respawn_fire_key )
PlayerCfg . RespawnMode = RespawnPress : : Fire ;
2010-01-17 14:42:59 +00:00
break ;
2015-02-28 22:34:07 +00:00
}
2010-01-17 14:42:59 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
2015-05-14 02:23:13 +00:00
const auto citem = static_cast < const d_select_event & > ( event ) . citem ;
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_confkey )
2015-11-01 21:15:38 +00:00
kconfig ( kconfig_type : : keyboard ) ;
2015-11-01 21:15:40 +00:00
# if MAX_JOYSTICKS
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_confjoy )
2015-11-01 21:15:38 +00:00
kconfig ( kconfig_type : : joystick ) ;
2015-11-01 21:15:40 +00:00
# endif
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_confmouse )
2015-11-01 21:15:38 +00:00
kconfig ( kconfig_type : : mouse ) ;
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_confweap )
2015-11-01 21:15:38 +00:00
kconfig ( kconfig_type : : rebirth ) ;
2015-09-25 21:59:20 +00:00
if ( citem = = opt_ic_keyboard )
input_config_keyboard ( ) ;
if ( citem = = opt_ic_mouse )
input_config_mouse ( ) ;
2015-11-01 21:15:40 +00:00
# if MAX_AXES_PER_JOYSTICK
2015-09-25 21:59:20 +00:00
if ( citem = = opt_ic_joystick )
input_config_joystick ( ) ;
2015-11-01 21:15:40 +00:00
# endif
2010-12-28 18:11:10 +00:00
if ( citem = = opt_ic_help0 )
show_help ( ) ;
if ( citem = = opt_ic_help1 )
show_netgame_help ( ) ;
if ( citem = = opt_ic_help2 )
show_newdemo_help ( ) ;
2010-01-30 03:24:19 +00:00
return 1 ; // stay in menu
2015-02-28 22:34:07 +00:00
}
2010-06-14 08:13:16 +00:00
2010-01-17 14:42:59 +00:00
default :
2010-01-30 03:24:19 +00:00
break ;
2008-02-24 14:41:27 +00:00
}
2010-06-14 08:13:16 +00:00
2010-01-30 03:24:19 +00:00
return 0 ;
2008-02-24 14:41:27 +00:00
}
void input_config ( )
{
2015-05-14 02:23:13 +00:00
input_config_menu_items menu_items ;
2015-11-01 21:15:40 +00:00
newmenu_do1 ( nullptr , TXT_CONTROLS , menu_items . m . size ( ) , menu_items . m . data ( ) , & input_config_menu_items : : menuset , & menu_items , menu_items . opt_ic_confkey ) ;
2008-02-24 14:41:27 +00:00
}
2013-10-27 22:00:14 +00:00
static void reticle_config ( )
2009-05-03 12:31:30 +00:00
{
2011-01-10 15:12:04 +00:00
# ifdef OGL
2015-05-14 02:23:13 +00:00
# define DXX_RETICLE_TYPE_OGL(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , RADIO , " Classic Reboot " , opt_reticle_classic_reboot , 0 , optgrp_reticle )
2011-01-10 15:12:04 +00:00
# else
2015-05-14 02:23:13 +00:00
# define DXX_RETICLE_TYPE_OGL(VERB)
2011-01-10 15:12:04 +00:00
# endif
2015-05-14 02:23:13 +00:00
# define DXX_RETICLE_CONFIG_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " Reticle Type: " , opt_label_reticle_type ) \
DXX_MENUITEM ( VERB , RADIO , " Classic " , opt_reticle_classic , 0 , optgrp_reticle ) \
2015-05-14 02:23:13 +00:00
DXX_RETICLE_TYPE_OGL ( VERB ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , RADIO , " None " , opt_reticle_none , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , RADIO , " X " , opt_reticle_x , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , RADIO , " Dot " , opt_reticle_dot , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , RADIO , " Circle " , opt_reticle_circle , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , RADIO , " Cross V1 " , opt_reticle_cross1 , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , RADIO , " Cross V2 " , opt_reticle_cross2 , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , RADIO , " Angle " , opt_reticle_angle , 0 , optgrp_reticle ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_reticle_type ) \
DXX_MENUITEM ( VERB , TEXT , " Reticle Color: " , opt_label_reticle_color ) \
DXX_MENUITEM ( VERB , SCALE_SLIDER , " Red " , opt_reticle_color_red , PlayerCfg . ReticleRGBA [ 0 ] , 0 , 16 , 2 ) \
DXX_MENUITEM ( VERB , SCALE_SLIDER , " Green " , opt_reticle_color_green , PlayerCfg . ReticleRGBA [ 1 ] , 0 , 16 , 2 ) \
DXX_MENUITEM ( VERB , SCALE_SLIDER , " Blue " , opt_reticle_color_blue , PlayerCfg . ReticleRGBA [ 2 ] , 0 , 16 , 2 ) \
DXX_MENUITEM ( VERB , SCALE_SLIDER , " Alpha " , opt_reticle_color_alpha , PlayerCfg . ReticleRGBA [ 3 ] , 0 , 16 , 2 ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank_reticle_color ) \
DXX_MENUITEM ( VERB , SLIDER , " Reticle Size: " , opt_label_reticle_size , PlayerCfg . ReticleSize , 0 , 4 ) \
2009-05-03 12:31:30 +00:00
2015-05-14 02:23:13 +00:00
class menu_items
{
public :
enum
{
optgrp_reticle ,
} ;
enum
{
DXX_RETICLE_CONFIG_MENU ( ENUM )
} ;
array < newmenu_item , DXX_RETICLE_CONFIG_MENU ( COUNT ) > m ;
menu_items ( )
{
DXX_RETICLE_CONFIG_MENU ( ADD ) ;
}
void read ( )
{
DXX_RETICLE_CONFIG_MENU ( READ ) ;
}
} ;
# undef DXX_RETICLE_CONFIG_MENU
# undef DXX_RETICLE_TYPE_OGL
menu_items items ;
2016-02-12 04:02:28 +00:00
{
2015-05-14 02:23:13 +00:00
auto i = PlayerCfg . ReticleType ;
2011-01-10 15:12:04 +00:00
# ifndef OGL
if ( i > 1 ) i - - ;
# endif
2015-05-14 02:23:13 +00:00
items . m [ items . opt_reticle_classic + i ] . value = 1 ;
2016-02-12 04:02:28 +00:00
}
2011-01-10 15:12:04 +00:00
2015-09-26 17:48:57 +00:00
newmenu_do1 ( nullptr , " Reticle Customization " , items . m . size ( ) , items . m . data ( ) , unused_newmenu_subfunction , unused_newmenu_userdata , 1 ) ;
2011-01-10 15:12:04 +00:00
2015-05-14 02:23:13 +00:00
for ( uint_fast32_t i = items . opt_reticle_classic ; i ! = items . opt_label_blank_reticle_type ; + + i )
if ( items . m [ i ] . value )
{
# ifndef OGL
if ( i ! = items . opt_reticle_classic )
+ + i ;
2011-01-10 15:12:04 +00:00
# endif
2015-05-14 02:23:13 +00:00
PlayerCfg . ReticleType = i - items . opt_reticle_classic ;
break ;
}
items . read ( ) ;
2011-01-10 15:12:04 +00:00
}
2015-09-26 17:48:57 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define DXX_GAME_SPECIFIC_HUDOPTIONS(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " Always-on Bomb Counter " , opt_d2bomb , PlayerCfg . BombGauge ) \
2015-09-26 17:48:57 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2015-09-26 21:17:14 +00:00
enum {
optgrp_missileview ,
} ;
2015-09-26 17:48:57 +00:00
# define DXX_GAME_SPECIFIC_HUDOPTIONS(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " Missile view: " , opt_missileview_label ) \
DXX_MENUITEM ( VERB , RADIO , " Disabled " , opt_missileview_none , PlayerCfg . MissileViewEnabled = = MissileViewMode : : None , optgrp_missileview ) \
DXX_MENUITEM ( VERB , RADIO , " Only own missiles " , opt_missileview_selfonly , PlayerCfg . MissileViewEnabled = = MissileViewMode : : EnabledSelfOnly , optgrp_missileview ) \
DXX_MENUITEM ( VERB , RADIO , " Friendly missiles, preferring self " , opt_missileview_selfandallies , PlayerCfg . MissileViewEnabled = = MissileViewMode : : EnabledSelfAndAllies , optgrp_missileview ) \
DXX_MENUITEM ( VERB , CHECK , " Show guided missile in main display " , opt_guidedbigview , PlayerCfg . GuidedInBigWindow ) \
2015-09-26 17:48:57 +00:00
# endif
# define DXX_HUD_MENU_OPTIONS(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , MENU , " Reticle Customization... " , opt_hud_reticlemenu ) \
DXX_MENUITEM ( VERB , CHECK , " Screenshots without HUD " , opt_screenshot , PlayerCfg . PRShot ) \
DXX_MENUITEM ( VERB , CHECK , " No redundant pickup messages " , opt_redundant , PlayerCfg . NoRedundancy ) \
DXX_MENUITEM ( VERB , CHECK , " Show Player chat only (Multi) " , opt_playerchat , PlayerCfg . MultiMessages ) \
2016-03-30 18:09:46 +00:00
DXX_MENUITEM ( VERB , CHECK , " Show Player ping (Multi) " , opt_playerping , PlayerCfg . MultiPingHud ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " Cloak/Invulnerability Timers " , opt_cloakinvultimer , PlayerCfg . CloakInvulTimer ) \
2015-09-26 17:48:57 +00:00
DXX_GAME_SPECIFIC_HUDOPTIONS ( VERB ) \
enum {
DXX_HUD_MENU_OPTIONS ( ENUM )
} ;
static int hud_config_menuset ( newmenu * , const d_event & event , const unused_newmenu_userdata_t * )
{
switch ( event . type )
{
case EVENT_NEWMENU_SELECTED :
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
if ( citem = = opt_hud_reticlemenu )
reticle_config ( ) ;
return 1 ; // stay in menu
}
default :
break ;
}
return 0 ;
}
void hud_config ( )
{
int i = 0 ;
do {
newmenu_item m [ DXX_HUD_MENU_OPTIONS ( COUNT ) ] ;
DXX_HUD_MENU_OPTIONS ( ADD ) ;
i = newmenu_do1 ( NULL , " Hud Options " , sizeof ( m ) / sizeof ( * m ) , m , hud_config_menuset , unused_newmenu_userdata , 0 ) ;
DXX_HUD_MENU_OPTIONS ( READ ) ;
2015-09-26 21:17:14 +00:00
# if defined(DXX_BUILD_DESCENT_II)
PlayerCfg . MissileViewEnabled = m [ opt_missileview_selfandallies ] . value
? MissileViewMode : : EnabledSelfAndAllies
: ( m [ opt_missileview_selfonly ] . value
? MissileViewMode : : EnabledSelfOnly
: MissileViewMode : : None ) ;
# endif
2015-09-26 17:48:57 +00:00
} while ( i > - 1 ) ;
}
2015-03-07 17:20:41 +00:00
# define DXX_GRAPHICS_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , MENU , " Screen resolution... " , opt_gr_screenres ) \
DXX_MENUITEM ( VERB , MENU , " HUD Options... " , opt_gr_hudmenu ) \
DXX_MENUITEM ( VERB , SLIDER , TXT_BRIGHTNESS , opt_gr_brightness , gr_palette_get_gamma ( ) , 0 , 16 ) \
DXX_MENUITEM ( VERB , TEXT , " " , blank1 ) \
2015-09-26 17:48:57 +00:00
DXX_OGL0_GRAPHICS_MENU ( VERB ) \
2015-03-07 17:20:41 +00:00
DXX_OGL1_GRAPHICS_MENU ( VERB ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " FPS Counter " , opt_gr_fpsindi , GameCfg . FPSIndicator ) \
2015-02-28 22:34:07 +00:00
2015-03-07 17:20:41 +00:00
# ifdef OGL
enum {
optgrp_texfilt ,
} ;
# define DXX_OGL0_GRAPHICS_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " Texture Filtering: " , opt_gr_texfilt ) \
DXX_MENUITEM ( VERB , RADIO , " None (Classical) " , opt_filter_none , 0 , optgrp_texfilt ) \
DXX_MENUITEM ( VERB , RADIO , " Bilinear " , opt_filter_bilinear , 0 , optgrp_texfilt ) \
DXX_MENUITEM ( VERB , RADIO , " Trilinear " , opt_filter_trilinear , 0 , optgrp_texfilt ) \
DXX_MENUITEM ( VERB , RADIO , " Anisotropic " , opt_filter_anisotropic , 0 , optgrp_texfilt ) \
2015-03-07 17:20:41 +00:00
D2X_OGL_GRAPHICS_MENU ( VERB ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , blank2 ) \
2015-03-07 17:20:41 +00:00
# define DXX_OGL1_GRAPHICS_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " Transparency Effects " , opt_gr_alphafx , PlayerCfg . AlphaEffects ) \
DXX_MENUITEM ( VERB , CHECK , " Colored Dynamic Light " , opt_gr_dynlightcolor , PlayerCfg . DynLightColor ) \
DXX_MENUITEM ( VERB , CHECK , " VSync " , opt_gr_vsync , CGameCfg . VSync ) \
DXX_MENUITEM ( VERB , CHECK , " 4x multisampling " , opt_gr_multisample , GameCfg . Multisample ) \
2015-03-07 17:20:41 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define D2X_OGL_GRAPHICS_MENU(VERB)
# elif defined(DXX_BUILD_DESCENT_II)
# define D2X_OGL_GRAPHICS_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " Movie Filter " , opt_gr_movietexfilt , GameCfg . MovieTexFilt )
2013-03-03 01:03:33 +00:00
# endif
2015-02-28 22:34:07 +00:00
2015-03-07 17:20:41 +00:00
# else
# define DXX_OGL0_GRAPHICS_MENU(VERB)
# define DXX_OGL1_GRAPHICS_MENU(VERB)
# endif
enum {
DXX_GRAPHICS_MENU ( ENUM )
} ;
2015-02-28 22:34:07 +00:00
2015-05-09 17:39:02 +00:00
static int graphics_config_menuset ( newmenu * , const d_event & event , newmenu_item * const items )
2011-01-10 15:12:04 +00:00
{
2014-10-04 21:47:13 +00:00
switch ( event . type )
2011-01-10 15:12:04 +00:00
{
case EVENT_NEWMENU_CHANGED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_change_event & > ( event ) . citem ;
2015-05-09 17:39:02 +00:00
if ( citem = = opt_gr_brightness )
gr_palette_set_gamma ( items [ citem ] . value ) ;
2011-01-17 04:38:32 +00:00
# ifdef OGL
2015-05-09 17:39:02 +00:00
else
2015-03-11 02:19:15 +00:00
if ( citem = = opt_filter_anisotropic & & ogl_maxanisotropy < = 1.0 )
2011-01-16 00:50:42 +00:00
{
nm_messagebox ( TXT_ERROR , 1 , TXT_OK , " Anisotropic Filtering not \n supported by your hardware/driver. " ) ;
2015-03-11 02:19:15 +00:00
items [ opt_filter_trilinear ] . value = 1 ;
items [ opt_filter_anisotropic ] . value = 0 ;
2011-01-16 00:50:42 +00:00
}
2015-03-11 02:19:15 +00:00
# endif
2011-01-10 15:12:04 +00:00
break ;
2015-02-28 22:34:07 +00:00
}
2011-01-10 15:12:04 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
2015-09-26 17:48:57 +00:00
if ( citem = = opt_gr_screenres )
change_res ( ) ;
if ( citem = = opt_gr_hudmenu )
hud_config ( ) ;
2011-01-10 15:12:04 +00:00
return 1 ; // stay in menu
2015-02-28 22:34:07 +00:00
}
2011-01-10 15:12:04 +00:00
default :
break ;
}
return 0 ;
}
void graphics_config ( )
{
2015-03-07 17:20:41 +00:00
array < newmenu_item , DXX_GRAPHICS_MENU ( COUNT ) > m ;
DXX_GRAPHICS_MENU ( ADD ) ;
2011-01-10 15:12:04 +00:00
2011-02-14 21:27:07 +00:00
# ifdef OGL
2015-12-18 04:08:23 +00:00
m [ opt_filter_none + CGameCfg . TexFilt ] . value = 1 ;
2011-01-10 15:12:04 +00:00
# endif
2015-09-26 17:48:57 +00:00
newmenu_do1 ( nullptr , " Graphics Options " , m . size ( ) , m . data ( ) , graphics_config_menuset , m . data ( ) , 0 ) ;
2011-01-10 15:12:04 +00:00
# ifdef OGL
2015-07-18 03:49:47 +00:00
if ( CGameCfg . VSync ! = m [ opt_gr_vsync ] . value | | GameCfg . Multisample ! = m [ opt_gr_multisample ] . value )
2013-06-10 23:07:12 +00:00
nm_messagebox ( NULL , 1 , TXT_OK , " Setting VSync or 4x Multisample \n requires restart on some systems. " ) ;
2011-01-10 15:12:04 +00:00
2015-03-07 17:20:41 +00:00
for ( uint_fast32_t i = 0 ; i ! = 4 ; + + i )
2015-04-07 01:55:57 +00:00
if ( m [ i + opt_filter_none ] . value )
2015-03-07 17:20:41 +00:00
{
2015-12-18 04:08:23 +00:00
CGameCfg . TexFilt = i ;
2015-03-07 17:20:41 +00:00
break ;
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2011-01-10 15:12:04 +00:00
GameCfg . MovieTexFilt = m [ opt_gr_movietexfilt ] . value ;
2013-03-03 01:03:33 +00:00
# endif
2011-02-23 16:46:39 +00:00
PlayerCfg . AlphaEffects = m [ opt_gr_alphafx ] . value ;
2011-04-07 20:32:51 +00:00
PlayerCfg . DynLightColor = m [ opt_gr_dynlightcolor ] . value ;
2015-07-18 03:49:47 +00:00
CGameCfg . VSync = m [ opt_gr_vsync ] . value ;
2011-01-10 15:12:04 +00:00
GameCfg . Multisample = m [ opt_gr_multisample ] . value ;
# endif
GameCfg . GammaLevel = m [ opt_gr_brightness ] . value ;
2011-02-14 21:27:07 +00:00
GameCfg . FPSIndicator = m [ opt_gr_fpsindi ] . value ;
2011-01-10 15:12:04 +00:00
# ifdef OGL
gr_set_attributes ( ) ;
gr_set_mode ( Game_screen_mode ) ;
# endif
2009-05-03 12:31:30 +00:00
}
2010-10-10 10:48:24 +00:00
# if PHYSFS_VER_MAJOR >= 2
2015-04-22 02:44:30 +00:00
namespace {
2013-12-22 22:03:07 +00:00
struct browser
2010-08-27 14:09:19 +00:00
{
2016-01-29 04:05:47 +00:00
browser ( const partial_range_t < const file_extension_t * > & r ) :
ext_range ( r )
{
}
2013-09-02 23:21:13 +00:00
const char * title ; // The title - needed for making another listbox when changing directory
2010-08-27 14:09:19 +00:00
int ( * when_selected ) ( void * userdata , const char * filename ) ; // What to do when something chosen
void * userdata ; // Whatever you want passed to when_selected
2014-09-28 23:28:56 +00:00
string_array_t list ;
2016-01-29 04:05:47 +00:00
// List of file extensions we're looking for (if looking for a music file many types are possible)
const partial_range_t < const file_extension_t * > ext_range ;
2010-08-27 14:09:19 +00:00
int select_dir ; // Allow selecting the current directory (e.g. for Jukebox level song directory)
int new_path ; // Whether the view_path is a new searchpath, if so, remove it when finished
2015-02-14 22:48:28 +00:00
char view_path [ PATH_MAX ] ; // The absolute path we're currently looking at
2013-12-22 22:03:07 +00:00
} ;
2010-08-27 14:09:19 +00:00
2015-04-22 02:44:30 +00:00
}
2014-10-17 01:59:12 +00:00
static void list_dir_el ( void * vb , const char * , const char * fname )
2010-08-27 14:09:19 +00:00
{
2014-10-17 01:59:12 +00:00
browser * b = reinterpret_cast < browser * > ( vb ) ;
2014-12-20 04:36:11 +00:00
const char * r = PHYSFS_getRealDir ( fname ) ;
if ( ! r )
r = " " ;
2016-01-29 04:05:47 +00:00
if ( ! strcmp ( r , b - > view_path ) & & ( PHYSFS_isDirectory ( fname ) | | PHYSFSX_checkMatchingExtension ( fname , b - > ext_range ) )
2015-09-13 20:23:05 +00:00
# if defined(__APPLE__) && defined(__MACH__)
2012-05-18 23:36:43 +00:00
& & d_stricmp ( fname , " Volumes " ) // this messes things up, use '..' instead
2010-08-27 14:09:19 +00:00
# endif
)
2014-09-28 23:28:56 +00:00
b - > list . add ( fname ) ;
2010-08-27 14:09:19 +00:00
}
2013-10-27 22:00:14 +00:00
static int list_directory ( browser * b )
2010-08-27 14:09:19 +00:00
{
2014-09-28 23:28:56 +00:00
b - > list . clear ( ) ;
b - > list . add ( " .. " ) ; // go to parent directory
2010-08-27 14:09:19 +00:00
if ( b - > select_dir )
{
2014-09-28 23:28:56 +00:00
b - > list . add ( " <this directory> " ) ; // choose the directory being viewed
2010-08-27 14:09:19 +00:00
}
2014-10-17 01:59:12 +00:00
PHYSFS_enumerateFilesCallback ( " " , list_dir_el , b ) ;
2014-09-28 23:28:56 +00:00
b - > list . tidy ( 1 + ( b - > select_dir ? 1 : 0 ) ,
2014-09-02 22:10:34 +00:00
# ifdef __linux__
2010-09-26 13:15:20 +00:00
strcmp
2010-08-27 14:09:19 +00:00
# else
2012-05-18 23:36:43 +00:00
d_stricmp
2010-08-27 14:09:19 +00:00
# endif
2010-09-26 13:15:20 +00:00
) ;
2010-08-27 14:09:19 +00:00
return 1 ;
}
2014-10-04 21:47:13 +00:00
static int select_file_handler ( listbox * menu , const d_event & event , browser * b )
2010-08-27 14:09:19 +00:00
{
char newpath [ PATH_MAX ] ;
2013-09-02 23:21:13 +00:00
const char * * list = listbox_get_items ( menu ) ;
2010-08-27 14:09:19 +00:00
const char * sep = PHYSFS_getDirSeparator ( ) ;
2010-08-27 20:32:05 +00:00
memset ( newpath , 0 , sizeof ( char ) * PATH_MAX ) ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-08-27 14:09:19 +00:00
{
2010-08-31 13:25:45 +00:00
# ifdef _WIN32
case EVENT_KEY_COMMAND :
{
2011-01-14 09:51:13 +00:00
if ( event_key_get ( event ) = = KEY_CTRLED + KEY_D )
2010-08-31 13:25:45 +00:00
{
2013-12-08 16:53:10 +00:00
char text [ 4 ] = " c " ;
2010-08-31 13:25:45 +00:00
int rval = 0 ;
2015-04-02 02:36:52 +00:00
array < newmenu_item , 1 > m { {
2015-01-18 01:58:31 +00:00
nm_item_input ( text ) ,
2015-04-02 02:36:52 +00:00
} } ;
2015-01-18 01:58:32 +00:00
rval = newmenu_do ( NULL , " Enter drive letter " , m , unused_newmenu_subfunction , unused_newmenu_userdata ) ;
2010-08-31 13:25:45 +00:00
text [ 1 ] = ' \0 ' ;
snprintf ( newpath , sizeof ( char ) * PATH_MAX , " %s:%s " , text , sep ) ;
2013-12-03 23:21:36 +00:00
if ( ! rval & & text [ 0 ] )
2010-08-31 13:25:45 +00:00
{
2016-01-29 04:05:47 +00:00
select_file_recursive ( b - > title , newpath , b - > ext_range , b - > select_dir , b - > when_selected , b - > userdata ) ;
2010-08-31 13:25:45 +00:00
// close old box.
window_close ( listbox_get_window ( menu ) ) ;
}
return 0 ;
}
break ;
}
# endif
2010-08-27 14:09:19 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
2010-08-27 14:09:19 +00:00
strcpy ( newpath , b - > view_path ) ;
if ( citem = = 0 ) // go to parent dir
{
char * p ;
2013-12-03 23:21:36 +00:00
size_t len_newpath = strlen ( newpath ) ;
size_t len_sep = strlen ( sep ) ;
if ( ( p = strstr ( & newpath [ len_newpath - len_sep ] , sep ) ) )
2010-08-27 14:09:19 +00:00
if ( p ! = strstr ( newpath , sep ) ) // if this isn't the only separator (i.e. it's not about to look at the root)
* p = 0 ;
2013-12-03 23:21:36 +00:00
p = newpath + len_newpath - 1 ;
while ( ( p > newpath ) & & strncmp ( p , sep , len_sep ) ) // make sure full separator string is matched (typically is)
2010-08-27 14:09:19 +00:00
p - - ;
if ( p = = strstr ( newpath , sep ) ) // Look at root directory next, if not already
{
2015-09-13 20:23:05 +00:00
# if defined(__APPLE__) && defined(__MACH__)
2012-05-18 23:36:43 +00:00
if ( ! d_stricmp ( p , " /Volumes " ) )
2010-08-27 14:09:19 +00:00
return 1 ;
# endif
2013-12-03 23:21:36 +00:00
if ( p [ len_sep ] ! = ' \0 ' )
p [ len_sep ] = ' \0 ' ;
2010-08-27 14:09:19 +00:00
else
{
2015-09-13 20:23:05 +00:00
# if defined(__APPLE__) && defined(__MACH__)
2010-08-27 14:09:19 +00:00
// For Mac OS X, list all active volumes if we leave the root
strcpy ( newpath , " /Volumes " ) ;
# else
return 1 ;
# endif
}
}
else
* p = ' \0 ' ;
}
else if ( citem = = 1 & & b - > select_dir )
return ! ( * b - > when_selected ) ( b - > userdata , " " ) ;
else
{
2013-12-03 23:21:36 +00:00
size_t len_newpath = strlen ( newpath ) ;
size_t len_sep = strlen ( sep ) ;
if ( strncmp ( & newpath [ len_newpath - len_sep ] , sep , len_sep ) )
2010-08-27 14:09:19 +00:00
{
2013-12-03 23:21:36 +00:00
strncat ( newpath , sep , PATH_MAX - 1 - len_newpath ) ;
2010-08-27 14:09:19 +00:00
newpath [ PATH_MAX - 1 ] = ' \0 ' ;
}
2013-12-03 23:21:36 +00:00
strncat ( newpath , list [ citem ] , PATH_MAX - 1 - len_newpath ) ;
2010-08-27 14:09:19 +00:00
newpath [ PATH_MAX - 1 ] = ' \0 ' ;
}
if ( ( citem = = 0 ) | | PHYSFS_isDirectory ( list [ citem ] ) )
{
// If it fails, stay in this one
2016-01-29 04:05:47 +00:00
return ! select_file_recursive ( b - > title , newpath , b - > ext_range , b - > select_dir , b - > when_selected , b - > userdata ) ;
2010-08-27 14:09:19 +00:00
}
return ! ( * b - > when_selected ) ( b - > userdata , list [ citem ] ) ;
2015-02-28 22:34:07 +00:00
}
2010-08-27 14:09:19 +00:00
case EVENT_WINDOW_CLOSE :
if ( b - > new_path )
PHYSFS_removeFromSearchPath ( b - > view_path ) ;
2014-12-22 04:35:47 +00:00
std : : default_delete < browser > ( ) ( b ) ;
2010-08-27 14:09:19 +00:00
break ;
default :
break ;
}
return 0 ;
}
2016-03-06 18:11:20 +00:00
static int select_file_recursive2 ( const char * title , const char * orig_path , const partial_range_t < const file_extension_t * > & ext_range , int select_dir , select_file_subfunction < void > when_selected , void * userdata )
2010-08-27 14:09:19 +00:00
{
const char * sep = PHYSFS_getDirSeparator ( ) ;
char * p ;
2011-04-18 12:32:36 +00:00
char new_path [ PATH_MAX ] ;
2010-08-27 14:09:19 +00:00
2016-01-29 04:05:47 +00:00
auto b = make_unique < browser > ( ext_range ) ;
2010-08-27 14:09:19 +00:00
b - > title = title ;
b - > when_selected = when_selected ;
b - > userdata = userdata ;
b - > select_dir = select_dir ;
b - > view_path [ 0 ] = ' \0 ' ;
b - > new_path = 1 ;
2011-04-18 12:32:36 +00:00
// Check for a PhysicsFS path first, saves complication!
2011-06-01 07:59:55 +00:00
if ( orig_path & & strncmp ( orig_path , sep , strlen ( sep ) ) & & PHYSFSX_exists ( orig_path , 0 ) )
2011-04-18 12:32:36 +00:00
{
PHYSFSX_getRealPath ( orig_path , new_path ) ;
orig_path = new_path ;
}
2010-08-27 14:09:19 +00:00
// Set the viewing directory to orig_path, or some parent of it
2010-08-28 02:46:54 +00:00
if ( orig_path )
2010-08-27 14:09:19 +00:00
{
2010-08-28 02:46:54 +00:00
// Must make this an absolute path for directory browsing to work properly
2010-08-31 13:25:45 +00:00
# ifdef _WIN32
2010-08-28 02:46:54 +00:00
if ( ! ( isalpha ( orig_path [ 0 ] ) & & ( orig_path [ 1 ] = = ' : ' ) ) ) // drive letter prompt (e.g. "C:"
# elif defined(macintosh)
if ( orig_path [ 0 ] = = ' : ' )
# else
if ( orig_path [ 0 ] ! = ' / ' )
# endif
{
strncpy ( b - > view_path , PHYSFS_getBaseDir ( ) , PATH_MAX - 1 ) ; // current write directory must be set to base directory
b - > view_path [ PATH_MAX - 1 ] = ' \0 ' ;
# ifdef macintosh
orig_path + + ; // go past ':'
# endif
strncat ( b - > view_path , orig_path , PATH_MAX - 1 - strlen ( b - > view_path ) ) ;
b - > view_path [ PATH_MAX - 1 ] = ' \0 ' ;
}
else
{
strncpy ( b - > view_path , orig_path , PATH_MAX - 1 ) ;
b - > view_path [ PATH_MAX - 1 ] = ' \0 ' ;
}
2010-08-27 14:09:19 +00:00
p = b - > view_path + strlen ( b - > view_path ) - 1 ;
2010-11-21 11:55:35 +00:00
b - > new_path = PHYSFSX_isNewPath ( b - > view_path ) ;
2010-08-27 14:09:19 +00:00
while ( ! PHYSFS_addToSearchPath ( b - > view_path , 0 ) )
{
2013-12-03 23:21:36 +00:00
size_t len_sep = strlen ( sep ) ;
while ( ( p > b - > view_path ) & & strncmp ( p , sep , len_sep ) )
2010-08-27 14:09:19 +00:00
p - - ;
* p = ' \0 ' ;
if ( p = = b - > view_path )
break ;
2010-11-21 11:55:35 +00:00
b - > new_path = PHYSFSX_isNewPath ( b - > view_path ) ;
2010-08-27 14:09:19 +00:00
}
}
// Set to user directory if we couldn't find a searchpath
if ( ! b - > view_path [ 0 ] )
{
strncpy ( b - > view_path , PHYSFS_getUserDir ( ) , PATH_MAX - 1 ) ;
b - > view_path [ PATH_MAX - 1 ] = ' \0 ' ;
2010-11-21 11:55:35 +00:00
b - > new_path = PHYSFSX_isNewPath ( b - > view_path ) ;
2010-08-27 14:09:19 +00:00
if ( ! PHYSFS_addToSearchPath ( b - > view_path , 0 ) )
{
return 0 ;
}
}
2014-09-28 23:28:56 +00:00
if ( ! list_directory ( b . get ( ) ) )
2010-08-27 14:09:19 +00:00
{
return 0 ;
}
2014-12-22 04:35:47 +00:00
auto pb = b . get ( ) ;
2015-01-17 18:31:42 +00:00
return newmenu_listbox1 ( title , pb - > list . pointer ( ) . size ( ) , & pb - > list . pointer ( ) . front ( ) , 1 , 0 , select_file_handler , std : : move ( b ) ) ! = NULL ;
2010-08-27 14:09:19 +00:00
}
2016-01-09 16:38:10 +00:00
# define DXX_MENU_ITEM_BROWSE(VERB, TXT, OPT) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , MENU , TXT " (browse...) " , OPT )
2010-10-10 10:48:24 +00:00
# else
2016-03-06 18:11:20 +00:00
int select_file_recursive2 ( const char * title , const char * orig_path , const partial_range_t < const file_extension_t * > & ext_range , int select_dir , int ( * when_selected ) ( void * userdata , const char * filename ) , void * userdata )
2010-10-10 10:48:24 +00:00
{
return 0 ;
}
2016-01-09 16:38:10 +00:00
/* Include blank string to force a compile error if TXT cannot be
* string - pasted
*/
# define DXX_MENU_ITEM_BROWSE(VERB, TXT, OPT) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , TXT " " , OPT )
2010-10-10 10:48:24 +00:00
# endif
2014-12-11 02:35:03 +00:00
# ifdef USE_SDLMIXER
2013-10-27 22:00:14 +00:00
static int get_absolute_path ( char * full_path , const char * rel_path )
2010-08-27 14:09:19 +00:00
{
2015-10-11 22:21:00 +00:00
PHYSFSX_getRealPath ( rel_path , full_path , PATH_MAX ) ;
2010-08-27 14:09:19 +00:00
return 1 ;
}
2016-08-06 19:55:25 +00:00
# define SELECT_SONG(t, s) select_file_recursive(t, CGameCfg.CMMiscMusic[s].data(), jukebox_exts, 0, get_absolute_path, CGameCfg.CMMiscMusic[s].data())
2010-10-14 09:50:11 +00:00
# endif
2010-08-27 14:09:19 +00:00
2016-01-09 16:38:10 +00:00
namespace {
# if defined(DXX_BUILD_DESCENT_I)
# define REDBOOK_PLAYORDER_TEXT "force mac cd track order"
# elif defined(DXX_BUILD_DESCENT_II)
# define REDBOOK_PLAYORDER_TEXT "force descent ][ cd track order"
# endif
# if defined(USE_SDLMIXER) || defined(_WIN32)
# define DXX_SOUND_ADDON_MUSIC_MENU_ITEM(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , RADIO , " Built-in/Addon music " , opt_sm_mtype1 , GameCfg . MusicType = = MUSIC_TYPE_BUILTIN , optgrp_music_type ) \
2016-01-09 16:38:10 +00:00
# else
# define DXX_SOUND_ADDON_MUSIC_MENU_ITEM(VERB)
# endif
# if SDL_MAJOR_VERSION == 1
# define DXX_SOUND_CD_MUSIC_MENU_ITEM(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , RADIO , " CD music " , opt_sm_mtype2 , GameCfg . MusicType = = MUSIC_TYPE_REDBOOK , optgrp_music_type ) \
2016-01-09 16:38:10 +00:00
# define DXX_MUSIC_OPTIONS_CD_LABEL "CD music"
# else
# define DXX_SOUND_CD_MUSIC_MENU_ITEM(VERB)
# define DXX_MUSIC_OPTIONS_CD_LABEL ""
# endif
# ifdef USE_SDLMIXER
# define DXX_SOUND_JUKEBOX_MENU_ITEM(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , RADIO , " Jukebox " , opt_sm_mtype3 , GameCfg . MusicType = = MUSIC_TYPE_CUSTOM , optgrp_music_type ) \
2016-01-09 16:38:10 +00:00
# define DXX_MUSIC_OPTIONS_JUKEBOX_LABEL "Jukebox"
# define DXX_SOUND_SDLMIXER_MENU_ITEMS(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank2 ) \
DXX_MENUITEM ( VERB , TEXT , " Jukebox options: " , opt_label_jukebox_options ) \
2016-01-09 16:38:10 +00:00
DXX_MENU_ITEM_BROWSE ( VERB , " Path for level music " , opt_sm_mtype3_lmpath ) \
2016-08-06 19:55:25 +00:00
DXX_MENUITEM ( VERB , INPUT , CGameCfg . CMLevelMusicPath , opt_sm_mtype3_lmpath_input ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank3 ) \
DXX_MENUITEM ( VERB , TEXT , " Level music play order: " , opt_label_lm_order ) \
DXX_MENUITEM ( VERB , RADIO , " continuous " , opt_sm_mtype3_lmplayorder1 , GameCfg . CMLevelMusicPlayOrder = = MUSIC_CM_PLAYORDER_CONT , optgrp_music_order ) \
DXX_MENUITEM ( VERB , RADIO , " one track per level " , opt_sm_mtype3_lmplayorder2 , GameCfg . CMLevelMusicPlayOrder = = MUSIC_CM_PLAYORDER_LEVEL , optgrp_music_order ) \
DXX_MENUITEM ( VERB , RADIO , " random " , opt_sm_mtype3_lmplayorder3 , GameCfg . CMLevelMusicPlayOrder = = MUSIC_CM_PLAYORDER_RAND , optgrp_music_order ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank4 ) \
DXX_MENUITEM ( VERB , TEXT , " Non-level music: " , opt_label_nonlevel_music ) \
2016-01-09 16:38:10 +00:00
DXX_MENU_ITEM_BROWSE ( VERB , " Main menu " , opt_sm_cm_mtype3_file1_b ) \
2016-08-06 19:55:25 +00:00
DXX_MENUITEM ( VERB , INPUT , CGameCfg . CMMiscMusic [ SONG_TITLE ] , opt_sm_cm_mtype3_file1 ) \
2016-01-09 16:38:10 +00:00
DXX_MENU_ITEM_BROWSE ( VERB , " Briefing " , opt_sm_cm_mtype3_file2_b ) \
2016-08-06 19:55:25 +00:00
DXX_MENUITEM ( VERB , INPUT , CGameCfg . CMMiscMusic [ SONG_BRIEFING ] , opt_sm_cm_mtype3_file2 ) \
2016-01-09 16:38:10 +00:00
DXX_MENU_ITEM_BROWSE ( VERB , " Credits " , opt_sm_cm_mtype3_file3_b ) \
2016-08-06 19:55:25 +00:00
DXX_MENUITEM ( VERB , INPUT , CGameCfg . CMMiscMusic [ SONG_CREDITS ] , opt_sm_cm_mtype3_file3 ) \
2016-01-09 16:38:10 +00:00
DXX_MENU_ITEM_BROWSE ( VERB , " Escape sequence " , opt_sm_cm_mtype3_file4_b ) \
2016-08-06 19:55:25 +00:00
DXX_MENUITEM ( VERB , INPUT , CGameCfg . CMMiscMusic [ SONG_ENDLEVEL ] , opt_sm_cm_mtype3_file4 ) \
2016-01-09 16:38:10 +00:00
DXX_MENU_ITEM_BROWSE ( VERB , " Game ending " , opt_sm_cm_mtype3_file5_b ) \
2016-08-06 19:55:25 +00:00
DXX_MENUITEM ( VERB , INPUT , CGameCfg . CMMiscMusic [ SONG_ENDGAME ] , opt_sm_cm_mtype3_file5 ) \
2016-01-09 16:38:10 +00:00
# else
# define DXX_SOUND_JUKEBOX_MENU_ITEM(VERB)
# define DXX_MUSIC_OPTIONS_JUKEBOX_LABEL ""
# define DXX_SOUND_SDLMIXER_MENU_ITEMS(VERB)
# endif
# if SDL_MAJOR_VERSION == 1 && defined(USE_SDLMIXER)
# define DXX_MUSIC_OPTIONS_SEPARATOR_TEXT " / "
# else
# define DXX_MUSIC_OPTIONS_SEPARATOR_TEXT ""
# endif
# define DXX_SOUND_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , SLIDER , TXT_FX_VOLUME , opt_sm_digivol , GameCfg . DigiVolume , 0 , 8 ) \
DXX_MENUITEM ( VERB , SLIDER , " Music volume " , opt_sm_musicvol , GameCfg . MusicVolume , 0 , 8 ) \
DXX_MENUITEM ( VERB , CHECK , TXT_REVERSE_STEREO , opt_sm_revstereo , GameCfg . ReverseStereo ) \
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank0 ) \
DXX_MENUITEM ( VERB , TEXT , " Music type: " , opt_label_music_type ) \
DXX_MENUITEM ( VERB , RADIO , " No music " , opt_sm_mtype0 , GameCfg . MusicType = = MUSIC_TYPE_NONE , optgrp_music_type ) \
2016-01-09 16:38:10 +00:00
DXX_SOUND_ADDON_MUSIC_MENU_ITEM ( VERB ) \
DXX_SOUND_CD_MUSIC_MENU_ITEM ( VERB ) \
DXX_SOUND_JUKEBOX_MENU_ITEM ( VERB ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank1 ) \
DXX_MENUITEM ( VERB , TEXT , DXX_MUSIC_OPTIONS_CD_LABEL DXX_MUSIC_OPTIONS_SEPARATOR_TEXT DXX_MUSIC_OPTIONS_JUKEBOX_LABEL " options: " , opt_label_music_options ) \
DXX_MENUITEM ( VERB , CHECK , REDBOOK_PLAYORDER_TEXT , opt_sm_redbook_playorder , GameCfg . OrigTrackOrder ) \
2016-01-09 16:38:10 +00:00
DXX_SOUND_SDLMIXER_MENU_ITEMS ( VERB ) \
class sound_menu_items
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:10 +00:00
public :
enum
{
optgrp_music_type ,
# ifdef USE_SDLMIXER
optgrp_music_order ,
# endif
} ;
enum
{
DXX_SOUND_MENU ( ENUM )
} ;
array < newmenu_item , DXX_SOUND_MENU ( COUNT ) > m ;
sound_menu_items ( )
{
DXX_SOUND_MENU ( ADD ) ;
}
void read ( )
{
DXX_SOUND_MENU ( READ ) ;
}
static int menuset ( newmenu * , const d_event & event , sound_menu_items * pitems ) ;
} ;
# undef DXX_SOUND_MENU
}
int sound_menu_items : : menuset ( newmenu * , const d_event & event , sound_menu_items * pitems )
{
const auto & items = pitems - > m ;
2010-02-26 08:42:44 +00:00
int replay = 0 ;
int rval = 0 ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-02-01 06:55:38 +00:00
{
case EVENT_NEWMENU_CHANGED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_change_event & > ( event ) . citem ;
2010-06-14 08:13:16 +00:00
if ( citem = = opt_sm_digivol )
2010-02-01 06:55:38 +00:00
{
2010-06-14 08:13:16 +00:00
GameCfg . DigiVolume = items [ citem ] . value ;
digi_set_digi_volume ( ( GameCfg . DigiVolume * 32768 ) / 8 ) ;
digi_play_sample_once ( SOUND_DROP_BOMB , F1_0 ) ;
}
else if ( citem = = opt_sm_musicvol )
{
GameCfg . MusicVolume = items [ citem ] . value ;
songs_set_volume ( GameCfg . MusicVolume ) ;
}
else if ( citem = = opt_sm_revstereo )
{
GameCfg . ReverseStereo = items [ citem ] . value ;
}
else if ( citem = = opt_sm_mtype0 )
{
GameCfg . MusicType = MUSIC_TYPE_NONE ;
replay = 1 ;
}
else if ( citem = = opt_sm_mtype1 )
{
GameCfg . MusicType = MUSIC_TYPE_BUILTIN ;
replay = 1 ;
}
else if ( citem = = opt_sm_mtype2 )
{
GameCfg . MusicType = MUSIC_TYPE_REDBOOK ;
replay = 1 ;
}
2010-10-14 09:50:11 +00:00
# ifdef USE_SDLMIXER
2010-06-14 08:13:16 +00:00
else if ( citem = = opt_sm_mtype3 )
{
GameCfg . MusicType = MUSIC_TYPE_CUSTOM ;
replay = 1 ;
}
2010-10-14 09:50:11 +00:00
# endif
2010-06-14 08:13:16 +00:00
else if ( citem = = opt_sm_redbook_playorder )
{
GameCfg . OrigTrackOrder = items [ citem ] . value ;
replay = ( Game_wind ! = NULL ) ;
}
2010-10-14 09:50:11 +00:00
# ifdef USE_SDLMIXER
2010-06-14 08:13:16 +00:00
else if ( citem = = opt_sm_mtype3_lmplayorder1 )
{
GameCfg . CMLevelMusicPlayOrder = MUSIC_CM_PLAYORDER_CONT ;
replay = ( Game_wind ! = NULL ) ;
}
else if ( citem = = opt_sm_mtype3_lmplayorder2 )
{
2010-08-17 14:59:57 +00:00
GameCfg . CMLevelMusicPlayOrder = MUSIC_CM_PLAYORDER_LEVEL ;
2010-06-14 08:13:16 +00:00
replay = ( Game_wind ! = NULL ) ;
2010-02-01 06:55:38 +00:00
}
2011-01-20 11:17:30 +00:00
else if ( citem = = opt_sm_mtype3_lmplayorder3 )
{
GameCfg . CMLevelMusicPlayOrder = MUSIC_CM_PLAYORDER_RAND ;
replay = ( Game_wind ! = NULL ) ;
}
2010-10-14 09:50:11 +00:00
# endif
2010-02-01 06:55:38 +00:00
break ;
2015-02-28 22:34:07 +00:00
}
2010-02-26 08:42:44 +00:00
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
2010-10-14 09:50:11 +00:00
# ifdef USE_SDLMIXER
2015-03-15 18:45:53 +00:00
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
2014-12-20 04:36:11 +00:00
# ifdef _WIN32
# define WINDOWS_DRIVE_CHANGE_TEXT ".\nCTRL-D to change drive"
# else
# define WINDOWS_DRIVE_CHANGE_TEXT
# endif
2010-08-27 14:09:19 +00:00
if ( citem = = opt_sm_mtype3_lmpath )
{
2015-03-22 18:49:21 +00:00
static const array < file_extension_t , 1 > ext_list { { " m3u " } } ; // select a directory or M3U playlist
2016-08-06 19:55:25 +00:00
const auto cfgpath = CGameCfg . CMLevelMusicPath . data ( ) ;
2010-08-31 13:25:45 +00:00
select_file_recursive (
2014-12-20 04:36:11 +00:00
" Select directory or \n M3U playlist to \n play level music from " WINDOWS_DRIVE_CHANGE_TEXT ,
2016-08-06 19:55:25 +00:00
cfgpath , ext_list , 1 , // look in current music path for ext_list files and allow directory selection
get_absolute_path , cfgpath ) ; // just copy the absolute path
2010-08-27 14:09:19 +00:00
}
else if ( citem = = opt_sm_cm_mtype3_file1_b )
2014-12-20 04:36:11 +00:00
SELECT_SONG ( " Select main menu music " WINDOWS_DRIVE_CHANGE_TEXT , SONG_TITLE ) ;
2010-08-27 14:09:19 +00:00
else if ( citem = = opt_sm_cm_mtype3_file2_b )
2014-12-20 04:36:11 +00:00
SELECT_SONG ( " Select briefing music " WINDOWS_DRIVE_CHANGE_TEXT , SONG_BRIEFING ) ;
2010-08-27 14:09:19 +00:00
else if ( citem = = opt_sm_cm_mtype3_file3_b )
2014-12-20 04:36:11 +00:00
SELECT_SONG ( " Select credits music " WINDOWS_DRIVE_CHANGE_TEXT , SONG_CREDITS ) ;
2010-08-27 14:09:19 +00:00
else if ( citem = = opt_sm_cm_mtype3_file4_b )
2014-12-20 04:36:11 +00:00
SELECT_SONG ( " Select escape sequence music " WINDOWS_DRIVE_CHANGE_TEXT , SONG_ENDLEVEL ) ;
2010-08-27 14:09:19 +00:00
else if ( citem = = opt_sm_cm_mtype3_file5_b )
2014-12-20 04:36:11 +00:00
SELECT_SONG ( " Select game ending music " WINDOWS_DRIVE_CHANGE_TEXT , SONG_ENDGAME ) ;
2010-10-14 09:50:11 +00:00
# endif
2010-02-26 08:42:44 +00:00
rval = 1 ; // stay in menu
break ;
2015-02-28 22:34:07 +00:00
}
2010-02-26 08:42:44 +00:00
case EVENT_WINDOW_CLOSE :
break ;
2010-06-14 08:13:16 +00:00
2010-02-01 06:55:38 +00:00
default :
break ;
2006-03-20 17:12:09 +00:00
}
2010-02-26 08:42:44 +00:00
if ( replay )
{
2010-06-14 08:13:16 +00:00
songs_uninit ( ) ;
2010-02-26 08:42:44 +00:00
if ( Game_wind )
2010-06-14 08:13:16 +00:00
songs_play_level_song ( Current_level_num , 0 ) ;
2010-02-26 08:42:44 +00:00
else
songs_play_song ( SONG_TITLE , 1 ) ;
}
2010-06-14 08:13:16 +00:00
2010-02-26 08:42:44 +00:00
return rval ;
2006-03-20 17:12:09 +00:00
}
2010-02-26 08:42:44 +00:00
void do_sound_menu ( )
{
2016-01-09 16:38:10 +00:00
2015-01-03 23:44:32 +00:00
# ifdef USE_SDLMIXER
2016-08-06 19:55:25 +00:00
const auto old_CMLevelMusicPath = CGameCfg . CMLevelMusicPath ;
2016-08-06 19:55:25 +00:00
const auto old_CMMiscMusic0 = CGameCfg . CMMiscMusic [ SONG_TITLE ] ;
2015-01-03 23:44:32 +00:00
# endif
2009-05-03 12:31:30 +00:00
2016-01-09 16:38:10 +00:00
sound_menu_items items ;
newmenu_do1 ( nullptr , " Sound Effects & Music " , items . m . size ( ) , items . m . data ( ) , & sound_menu_items : : menuset , & items , 0 ) ;
2010-06-14 08:13:16 +00:00
# ifdef USE_SDLMIXER
2016-08-06 19:55:25 +00:00
if ( ( Game_wind ! = NULL & & strcmp ( old_CMLevelMusicPath . data ( ) , CGameCfg . CMLevelMusicPath . data ( ) ) ) | | ( Game_wind = = NULL & & strcmp ( old_CMMiscMusic0 . data ( ) , CGameCfg . CMMiscMusic [ SONG_TITLE ] . data ( ) ) ) )
2010-06-14 08:13:16 +00:00
{
songs_uninit ( ) ;
if ( Game_wind )
songs_play_level_song ( Current_level_num , 0 ) ;
else
songs_play_song ( SONG_TITLE , 1 ) ;
}
# endif
2008-04-13 00:28:36 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define DXX_GAME_SPECIFIC_OPTIONS(VERB) \
# elif defined(DXX_BUILD_DESCENT_II)
# define DXX_GAME_SPECIFIC_OPTIONS(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " Headlight on when picked up " , opt_headlighton , PlayerCfg . HeadlightActiveDefault ) \
DXX_MENUITEM ( VERB , CHECK , " Escort robot hot keys " , opt_escorthotkey , PlayerCfg . EscortHotKeys ) \
DXX_MENUITEM ( VERB , CHECK , " Movie Subtitles " , opt_moviesubtitle , GameCfg . MovieSubtitles ) \
2013-03-03 01:03:33 +00:00
# endif
2015-10-18 18:11:57 +00:00
enum {
optgrp_autoselect_firing ,
} ;
2015-09-26 17:48:57 +00:00
# define DXX_GAMEPLAY_MENU_OPTIONS(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , CHECK , " Ship auto-leveling " , opt_autolevel , PlayerCfg . AutoLeveling ) \
DXX_MENUITEM ( VERB , CHECK , " Persistent Debris " , opt_persist_debris , PlayerCfg . PersistentDebris ) \
DXX_MENUITEM ( VERB , CHECK , " No Rankings (Multi) " , opt_noranking , PlayerCfg . NoRankings ) \
DXX_MENUITEM ( VERB , CHECK , " Free Flight in Automap " , opt_freeflight , PlayerCfg . AutomapFreeFlight ) \
2013-03-03 01:03:33 +00:00
DXX_GAME_SPECIFIC_OPTIONS ( VERB ) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , TEXT , " " , opt_label_blank ) \
DXX_MENUITEM ( VERB , TEXT , " Weapon Autoselect options: " , opt_label_autoselect ) \
DXX_MENUITEM ( VERB , MENU , " Primary ordering... " , opt_gameplay_reorderprimary_menu ) \
DXX_MENUITEM ( VERB , MENU , " Secondary ordering... " , opt_gameplay_reordersecondary_menu ) \
DXX_MENUITEM ( VERB , TEXT , " Autoselect while firing: " , opt_autoselect_firing_label ) \
DXX_MENUITEM ( VERB , RADIO , " Immediately " , opt_autoselect_firing_immediate , PlayerCfg . NoFireAutoselect = = FiringAutoselectMode : : Immediate , optgrp_autoselect_firing ) \
DXX_MENUITEM ( VERB , RADIO , " Never " , opt_autoselect_firing_never , PlayerCfg . NoFireAutoselect = = FiringAutoselectMode : : Never , optgrp_autoselect_firing ) \
DXX_MENUITEM ( VERB , RADIO , " When firing stops " , opt_autoselect_firing_delayed , PlayerCfg . NoFireAutoselect = = FiringAutoselectMode : : Delayed , optgrp_autoselect_firing ) \
DXX_MENUITEM ( VERB , CHECK , " Only Cycle Autoselect Weapons " , opt_only_autoselect , PlayerCfg . CycleAutoselectOnly ) \
2013-03-03 01:03:33 +00:00
2015-09-26 17:48:57 +00:00
enum {
DXX_GAMEPLAY_MENU_OPTIONS ( ENUM )
} ;
2006-03-20 17:12:09 +00:00
2015-09-26 17:48:57 +00:00
static int gameplay_config_menuset ( newmenu * , const d_event & event , const unused_newmenu_userdata_t * )
{
switch ( event . type )
{
case EVENT_NEWMENU_SELECTED :
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
if ( citem = = opt_gameplay_reorderprimary_menu )
ReorderPrimary ( ) ;
if ( citem = = opt_gameplay_reordersecondary_menu )
ReorderSecondary ( ) ;
return 1 ; // stay in menu
}
default :
break ;
}
return 0 ;
}
void gameplay_config ( )
2006-03-20 17:12:09 +00:00
{
int i = 0 ;
do {
2015-09-26 17:48:57 +00:00
newmenu_item m [ DXX_GAMEPLAY_MENU_OPTIONS ( COUNT ) ] ;
DXX_GAMEPLAY_MENU_OPTIONS ( ADD ) ;
i = newmenu_do1 ( NULL , " Gameplay Options " , sizeof ( m ) / sizeof ( * m ) , m , gameplay_config_menuset , unused_newmenu_userdata , 0 ) ;
DXX_GAMEPLAY_MENU_OPTIONS ( READ ) ;
2015-10-18 18:11:57 +00:00
PlayerCfg . NoFireAutoselect = m [ opt_autoselect_firing_delayed ] . value
? FiringAutoselectMode : : Delayed
: ( m [ opt_autoselect_firing_immediate ] . value
? FiringAutoselectMode : : Immediate
: FiringAutoselectMode : : Never ) ;
2006-03-20 17:12:09 +00:00
} while ( i > - 1 ) ;
}
2011-09-13 23:15:32 +00:00
# if defined(USE_UDP)
2014-10-04 21:47:13 +00:00
static int multi_player_menu_handler ( newmenu * menu , const d_event & event , int * menu_choice )
2010-04-04 09:41:53 +00:00
{
newmenu_item * items = newmenu_get_items ( menu ) ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2010-04-04 09:41:53 +00:00
{
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
2010-04-04 09:41:53 +00:00
// stay in multiplayer menu, even after having played a game
2015-02-28 22:34:07 +00:00
return do_option ( menu_choice [ citem ] ) ;
}
2010-06-14 08:13:16 +00:00
2010-04-04 09:41:53 +00:00
case EVENT_WINDOW_CLOSE :
d_free ( menu_choice ) ;
d_free ( items ) ;
break ;
2010-06-14 08:13:16 +00:00
2010-04-04 09:41:53 +00:00
default :
break ;
}
2010-06-14 08:13:16 +00:00
2010-04-04 09:41:53 +00:00
return 0 ;
}
2006-03-20 17:12:09 +00:00
void do_multi_player_menu ( )
{
2010-04-04 09:41:53 +00:00
int * menu_choice ;
newmenu_item * m ;
int num_options = 0 ;
2006-03-20 17:12:09 +00:00
2011-09-13 23:15:32 +00:00
MALLOC ( menu_choice , int , 3 ) ;
2010-04-04 09:41:53 +00:00
if ( ! menu_choice )
return ;
2010-06-14 08:13:16 +00:00
2011-09-13 23:15:32 +00:00
MALLOC ( m , newmenu_item , 3 ) ;
2010-04-04 09:41:53 +00:00
if ( ! m )
{
d_free ( menu_choice ) ;
return ;
}
2006-03-20 17:12:09 +00:00
2009-11-29 16:46:13 +00:00
# ifdef USE_UDP
2012-11-24 20:57:15 +00:00
ADD_ITEM ( " HOST GAME " , MENU_START_UDP_NETGAME , - 1 ) ;
2011-04-05 00:24:34 +00:00
# ifdef USE_TRACKER
2012-11-24 20:57:15 +00:00
ADD_ITEM ( " FIND LAN/ONLINE GAMES " , MENU_JOIN_LIST_UDP_NETGAME , - 1 ) ;
2011-04-05 00:24:34 +00:00
# else
2012-11-24 20:57:15 +00:00
ADD_ITEM ( " FIND LAN GAMES " , MENU_JOIN_LIST_UDP_NETGAME , - 1 ) ;
2011-04-05 00:24:34 +00:00
# endif
2012-11-24 20:57:15 +00:00
ADD_ITEM ( " JOIN GAME MANUALLY " , MENU_JOIN_MANUAL_UDP_NETGAME , - 1 ) ;
2009-11-29 16:46:13 +00:00
# endif
2009-11-24 09:48:53 +00:00
2013-12-04 22:45:33 +00:00
newmenu_do3 ( NULL , TXT_MULTIPLAYER , num_options , m , multi_player_menu_handler , menu_choice , 0 , NULL ) ;
2006-03-20 17:12:09 +00:00
}
2009-11-29 16:46:13 +00:00
# endif
2008-04-13 00:28:36 +00:00
void do_options_menu ( )
{
2015-03-07 17:20:40 +00:00
auto items = new options_menu_items ;
2010-04-04 09:41:53 +00:00
// Fall back to main event loop
// Allows clean closing and re-opening when resolution changes
2015-03-07 17:20:40 +00:00
newmenu_do3 ( nullptr , TXT_OPTIONS , items - > m . size ( ) , items - > m . data ( ) , options_menuset , items , 0 , nullptr ) ;
2008-04-13 00:28:36 +00:00
}
2011-07-20 12:44:49 +00:00
# ifndef RELEASE
2015-04-26 20:15:56 +00:00
static window_event_result polygon_models_viewer_handler ( window * , const d_event & event , const unused_window_userdata_t * )
2011-07-20 12:44:49 +00:00
{
2014-09-20 23:47:27 +00:00
static unsigned view_idx ;
2011-07-20 12:44:49 +00:00
int key = 0 ;
static vms_angvec ang ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2011-07-20 12:44:49 +00:00
{
case EVENT_WINDOW_ACTIVATED :
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2011-07-20 12:44:49 +00:00
gr_use_palette_table ( " groupa.256 " ) ;
2013-03-03 01:03:33 +00:00
# endif
2011-07-20 12:44:49 +00:00
key_toggle_repeat ( 1 ) ;
view_idx = 0 ;
ang . p = ang . b = 0 ;
2012-05-14 15:13:27 +00:00
ang . h = F0_5 - 1 ;
2011-07-20 12:44:49 +00:00
break ;
case EVENT_KEY_COMMAND :
key = event_key_get ( event ) ;
switch ( key )
{
case KEY_ESC :
2014-08-06 02:10:49 +00:00
return window_event_result : : close ;
2011-07-20 12:44:49 +00:00
case KEY_SPACEBAR :
view_idx + + ;
if ( view_idx > = N_polygon_models ) view_idx = 0 ;
break ;
case KEY_BACKSP :
2014-09-20 23:47:27 +00:00
if ( ! view_idx )
view_idx = N_polygon_models - 1 ;
else
view_idx - - ;
2011-07-20 12:44:49 +00:00
break ;
case KEY_A :
ang . h - = 100 ;
break ;
case KEY_D :
ang . h + = 100 ;
break ;
case KEY_W :
ang . p - = 100 ;
break ;
case KEY_S :
ang . p + = 100 ;
break ;
case KEY_Q :
ang . b - = 100 ;
break ;
case KEY_E :
ang . b + = 100 ;
break ;
case KEY_R :
ang . p = ang . b = 0 ;
2012-05-14 15:13:27 +00:00
ang . h = F0_5 - 1 ;
2011-07-20 12:44:49 +00:00
break ;
default :
break ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2011-07-20 12:44:49 +00:00
case EVENT_WINDOW_DRAW :
timer_delay ( F1_0 / 60 ) ;
draw_model_picture ( view_idx , & ang ) ;
gr_set_curfont ( GAME_FONT ) ;
gr_set_fontcolor ( BM_XRGB ( 255 , 255 , 255 ) , - 1 ) ;
gr_printf ( FSPACX ( 1 ) , FSPACY ( 1 ) , " ESC: leave \n SPACE/BACKSP: next/prev model (%i/%i) \n A/D: rotate y \n W/S: rotate x \n Q/E: rotate z \n R: reset orientation " , view_idx , N_polygon_models - 1 ) ;
break ;
case EVENT_WINDOW_CLOSE :
load_palette ( MENU_PALETTE , 0 , 1 ) ;
key_toggle_repeat ( 0 ) ;
break ;
default :
break ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ;
2011-07-20 12:44:49 +00:00
}
2013-10-27 22:00:14 +00:00
static void polygon_models_viewer ( )
2011-07-20 12:44:49 +00:00
{
2013-12-01 05:21:47 +00:00
window * wind = window_create ( & grd_curscreen - > sc_canvas , 0 , 0 , SWIDTH , SHEIGHT , polygon_models_viewer_handler , unused_window_userdata ) ;
2011-07-20 12:44:49 +00:00
if ( ! wind )
{
d_event event = { EVENT_WINDOW_CLOSE } ;
2014-10-04 21:47:13 +00:00
polygon_models_viewer_handler ( NULL , event , NULL ) ;
2011-07-20 12:44:49 +00:00
return ;
}
while ( window_exists ( wind ) )
event_process ( ) ;
}
2015-04-26 20:15:56 +00:00
static window_event_result gamebitmaps_viewer_handler ( window * , const d_event & event , const unused_window_userdata_t * )
2011-07-20 12:44:49 +00:00
{
static int view_idx = 0 ;
int key = 0 ;
# ifdef OGL
float scale = 1.0 ;
# endif
bitmap_index bi ;
grs_bitmap * bm ;
2014-10-04 21:47:13 +00:00
switch ( event . type )
2011-07-20 12:44:49 +00:00
{
case EVENT_WINDOW_ACTIVATED :
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2011-07-20 12:44:49 +00:00
gr_use_palette_table ( " groupa.256 " ) ;
2013-03-03 01:03:33 +00:00
# endif
2011-07-20 12:44:49 +00:00
key_toggle_repeat ( 1 ) ;
view_idx = 0 ;
break ;
case EVENT_KEY_COMMAND :
key = event_key_get ( event ) ;
switch ( key )
{
case KEY_ESC :
2014-08-06 02:10:49 +00:00
return window_event_result : : close ;
2011-07-20 12:44:49 +00:00
case KEY_SPACEBAR :
view_idx + + ;
if ( view_idx > = Num_bitmap_files ) view_idx = 0 ;
break ;
case KEY_BACKSP :
view_idx - - ;
if ( view_idx < 0 ) view_idx = Num_bitmap_files - 1 ;
break ;
default :
break ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : handled ;
2011-07-20 12:44:49 +00:00
case EVENT_WINDOW_DRAW :
bi . index = view_idx ;
bm = & GameBitmaps [ view_idx ] ;
timer_delay ( F1_0 / 60 ) ;
PIGGY_PAGE_IN ( bi ) ;
gr_clear_canvas ( BM_XRGB ( 0 , 0 , 0 ) ) ;
# ifdef OGL
scale = ( bm - > bm_w > bm - > bm_h ) ? ( SHEIGHT / bm - > bm_w ) * 0.8 : ( SHEIGHT / bm - > bm_h ) * 0.8 ;
2016-02-12 04:02:28 +00:00
ogl_ubitmapm_cs ( ( SWIDTH / 2 ) - ( bm - > bm_w * scale / 2 ) , ( SHEIGHT / 2 ) - ( bm - > bm_h * scale / 2 ) , bm - > bm_w * scale , bm - > bm_h * scale , * bm , ogl_colors : : white , F1_0 ) ;
2011-07-20 12:44:49 +00:00
# else
2014-12-02 03:35:01 +00:00
gr_bitmap ( ( SWIDTH / 2 ) - ( bm - > bm_w / 2 ) , ( SHEIGHT / 2 ) - ( bm - > bm_h / 2 ) , * bm ) ;
2011-07-20 12:44:49 +00:00
# endif
gr_set_curfont ( GAME_FONT ) ;
gr_set_fontcolor ( BM_XRGB ( 255 , 255 , 255 ) , - 1 ) ;
gr_printf ( FSPACX ( 1 ) , FSPACY ( 1 ) , " ESC: leave \n SPACE/BACKSP: next/prev bitmap (%i/%i) " , view_idx , Num_bitmap_files - 1 ) ;
break ;
case EVENT_WINDOW_CLOSE :
load_palette ( MENU_PALETTE , 0 , 1 ) ;
key_toggle_repeat ( 0 ) ;
break ;
default :
break ;
}
2014-08-06 02:10:49 +00:00
return window_event_result : : ignored ;
2011-07-20 12:44:49 +00:00
}
2013-10-27 22:00:14 +00:00
static void gamebitmaps_viewer ( )
2011-07-20 12:44:49 +00:00
{
2013-12-01 05:21:47 +00:00
window * wind = window_create ( & grd_curscreen - > sc_canvas , 0 , 0 , SWIDTH , SHEIGHT , gamebitmaps_viewer_handler , unused_window_userdata ) ;
2011-07-20 12:44:49 +00:00
if ( ! wind )
{
d_event event = { EVENT_WINDOW_CLOSE } ;
2014-10-04 21:47:13 +00:00
gamebitmaps_viewer_handler ( NULL , event , NULL ) ;
2011-07-20 12:44:49 +00:00
return ;
}
while ( window_exists ( wind ) )
event_process ( ) ;
}
2015-03-07 17:20:41 +00:00
# define DXX_SANDBOX_MENU(VERB) \
2016-01-09 16:38:17 +00:00
DXX_MENUITEM ( VERB , MENU , " Polygon_models viewer " , polygon_models ) \
DXX_MENUITEM ( VERB , MENU , " GameBitmaps viewer " , bitmaps ) \
2015-03-07 17:20:41 +00:00
namespace {
class sandbox_menu_items
{
public :
enum
{
DXX_SANDBOX_MENU ( ENUM )
} ;
array < newmenu_item , DXX_SANDBOX_MENU ( COUNT ) > m ;
sandbox_menu_items ( )
{
DXX_SANDBOX_MENU ( ADD ) ;
}
} ;
}
2015-04-26 20:15:56 +00:00
static int sandbox_menuset ( newmenu * , const d_event & event , sandbox_menu_items * items )
2011-07-20 12:44:49 +00:00
{
2014-10-04 21:47:13 +00:00
switch ( event . type )
2011-07-20 12:44:49 +00:00
{
case EVENT_NEWMENU_CHANGED :
break ;
case EVENT_NEWMENU_SELECTED :
2015-02-28 22:34:07 +00:00
{
auto & citem = static_cast < const d_select_event & > ( event ) . citem ;
switch ( citem )
2011-07-20 12:44:49 +00:00
{
2015-03-07 17:20:41 +00:00
case sandbox_menu_items : : polygon_models :
polygon_models_viewer ( ) ;
break ;
case sandbox_menu_items : : bitmaps :
gamebitmaps_viewer ( ) ;
break ;
2011-07-20 12:44:49 +00:00
}
return 1 ; // stay in menu until escape
2015-02-28 22:34:07 +00:00
}
2011-07-20 12:44:49 +00:00
case EVENT_WINDOW_CLOSE :
{
2015-03-07 17:20:41 +00:00
std : : default_delete < sandbox_menu_items > ( ) ( items ) ;
2011-07-20 12:44:49 +00:00
break ;
}
default :
break ;
}
return 0 ;
}
void do_sandbox_menu ( )
{
2015-03-07 17:20:41 +00:00
auto items = new sandbox_menu_items ;
newmenu_do3 ( nullptr , " Coder's sandbox " , items - > m . size ( ) , items - > m . data ( ) , sandbox_menuset , items , 0 , nullptr ) ;
2011-07-20 12:44:49 +00:00
}
# endif