1 #ifndef VG_SETTINGS_MENU_H
2 #define VG_SETTINGS_MENU_H
7 #ifdef VG_GAME_SETTINGS
8 static void vg_game_settings_gui( ui_rect panel
) ;
9 static void vg_game_settings_init(void);
12 struct ui_enum_opt vg_settings_vsync_enum
[] = {
18 struct ui_enum_opt vg_settings_quality_enum
[] = {
19 { 0, "High Quality" },
21 { 2, "Absolute Minimum" },
24 struct ui_enum_opt vg_settings_screen_mode_enum
[] = {
25 { 0, "Fullscreen (desktop)" },
26 { 1, "Fullscreen (native)" },
27 { 2, "Floating Window" }
30 struct ui_enum_opt vg_settings_dsp_enum
[] = {
36 struct vg_setting_ranged_i32
{
37 i32 new_value
, *actual_value
, min
, max
;
43 struct vg_setting_enum
{
44 i32 new_value
, *actual_value
;
46 struct ui_enum_opt
*options
;
50 vsync
, quality
, screenmode
, audio_devices
, dsp
;
51 i32 temp_audio_choice
;
53 int windowed_before
[4];
55 static vg_settings
= {
56 .fps_limit
= { .label
= "Fps Limit",
57 .min
=24, .max
=300, .actual_value
= &vg
.fps_limit
},
58 .vsync
= { .label
= "Vsync",
59 .actual_value
= &vg
.vsync
,
60 .options
= vg_settings_vsync_enum
, .option_count
= 3 },
61 .quality
= { .label
= "Graphic Quality",
62 .actual_value
= &vg
.quality_profile
,
63 .options
= vg_settings_quality_enum
, .option_count
= 3 },
64 .screenmode
= { .label
= "Type",
65 .actual_value
= &vg
.screen_mode
,
66 .options
= vg_settings_screen_mode_enum
, .option_count
=3 },
67 .audio_devices
= { .label
= "Audio Device",
68 .actual_value
= &vg_settings
.temp_audio_choice
,
69 .options
= NULL
, .option_count
= 0 },
70 .dsp
= { .label
= "Audio effects (reverb etc.)",
71 .actual_value
= &vg_audio
.dsp_enabled
,
72 .options
= vg_settings_dsp_enum
, .option_count
=2 },
75 static void vg_settings_ui_draw_diff( ui_rect orig
){
77 ui_split( orig
, k_ui_axis_v
, -32, 0, l
, r
);
78 ui_text( r
, "*", 1, k_ui_align_middle_center
, ui_colour(k_ui_blue
) );
82 * ------------------------------------------------------------------------- */
84 static void vg_settings_ui_int( char *buf
, u32 len
){
85 for( u32 i
=0, j
=0; i
<len
; i
++ ){
86 if( ((buf
[i
] >= '0') && (buf
[i
] <= '9')) || (buf
[i
] == '\0') )
91 struct ui_textbox_callbacks
static vg_settings_ui_int_callbacks
= {
92 .change
= vg_settings_ui_int
95 static bool vg_settings_ranged_i32_valid( struct vg_setting_ranged_i32
*prop
){
96 if( prop
->new_value
< prop
->min
) return 0;
97 if( prop
->new_value
> prop
->max
) return 0;
101 static bool vg_settings_ranged_i32_diff( struct vg_setting_ranged_i32
*prop
){
102 if( prop
->new_value
!= *prop
->actual_value
) return 1;
106 static bool vg_settings_ui_ranged_i32( struct vg_setting_ranged_i32
*prop
,
109 rect_copy( rect
, orig
);
111 ui_textbox( rect
, prop
->label
, prop
->buf
, sizeof(prop
->buf
),
112 1, 0, &vg_settings_ui_int_callbacks
);
113 prop
->new_value
= atoi( prop
->buf
);
115 if( vg_settings_ranged_i32_diff( prop
) )
116 vg_settings_ui_draw_diff( orig
);
118 bool valid
= vg_settings_ranged_i32_valid( prop
);
121 ui_split( orig
, k_ui_axis_h
, -1, 0, _null
, line
);
124 ui_fill( line
, ui_colour( k_ui_red
) );
130 static void ui_settings_ranged_i32_init( struct vg_setting_ranged_i32
*prop
){
132 vg_strnull( &tmp
, prop
->buf
, sizeof(prop
->buf
) );
133 vg_strcati32( &tmp
, *prop
->actual_value
);
134 prop
->new_value
= *prop
->actual_value
;
138 * ------------------------------------------------------------------------- */
140 static bool vg_settings_enum_diff( struct vg_setting_enum
*prop
){
141 if( prop
->new_value
!= *prop
->actual_value
) return 1;
145 static bool vg_settings_enum( struct vg_setting_enum
*prop
, ui_rect rect
){
147 rect_copy( rect
, orig
);
149 ui_enum( rect
, prop
->label
,
150 prop
->options
, prop
->option_count
, &prop
->new_value
);
152 if( vg_settings_enum_diff( prop
) )
153 vg_settings_ui_draw_diff( orig
);
158 static void ui_settings_enum_init( struct vg_setting_enum
*prop
){
159 prop
->new_value
= *prop
->actual_value
;
164 static void vg_settings_ui_header( ui_rect inout_panel
, const char *name
){
166 ui_standard_widget( inout_panel
, rect
, 2 );
167 ui_text( rect
, name
, 1, k_ui_align_middle_center
, ui_colour(k_ui_fg
+3) );
171 static bool vg_settings_apply_button( ui_rect inout_panel
, bool validated
){
173 ui_px height
= (vg_ui
.font
->glyph_height
+ 18) * k_ui_scale
;
174 ui_split( inout_panel
, k_ui_axis_h
, -height
, k_ui_padding
,
175 inout_panel
, last_row
);
177 const char *string
= "Apply";
179 if( ui_button( last_row
, string
) == 1 )
184 ui_standard_widget( last_row
, rect
, 1 );
185 ui_fill( rect
, ui_colour( k_ui_bg
+1 ) );
186 ui_outline( rect
, -1, ui_colour( k_ui_red
), 0 );
188 ui_rect t
= { 0,0, ui_text_line_width( string
), 14 };
189 ui_rect_center( rect
, t
);
190 ui_text( t
, string
, 1, k_ui_align_left
, ui_colour(k_ui_fg
+3) );
196 static void vg_settings_video_apply(void){
197 if( vg_settings_enum_diff( &vg_settings
.screenmode
) ){
198 vg
.screen_mode
= vg_settings
.screenmode
.new_value
;
200 if( (vg
.screen_mode
== 0) || (vg
.screen_mode
== 1) ){
201 SDL_GetWindowPosition( vg
.window
,
202 &vg_settings
.windowed_before
[0],
203 &vg_settings
.windowed_before
[1] );
204 vg_settings
.windowed_before
[2] = vg
.window_x
;
205 vg_settings
.windowed_before
[3] = vg
.window_y
;
207 SDL_DisplayMode video_mode
;
208 if( SDL_GetDesktopDisplayMode( 0, &video_mode
) ){
209 vg_error("SDL_GetDesktopDisplayMode failed: %s\n", SDL_GetError());
212 //vg.display_refresh_rate = video_mode.refresh_rate;
213 vg
.window_x
= video_mode
.w
;
214 vg
.window_y
= video_mode
.h
;
216 SDL_SetWindowResizable( vg
.window
, SDL_FALSE
);
217 SDL_SetWindowSize( vg
.window
, vg
.window_x
, vg
.window_y
);
220 if( vg
.screen_mode
== 0 )
221 SDL_SetWindowFullscreen( vg
.window
, SDL_WINDOW_FULLSCREEN_DESKTOP
);
222 if( vg
.screen_mode
== 1 )
223 SDL_SetWindowFullscreen( vg
.window
, SDL_WINDOW_FULLSCREEN
);
224 if( vg
.screen_mode
== 2 ){
225 SDL_SetWindowFullscreen( vg
.window
, 0 );
226 SDL_SetWindowSize( vg
.window
,
227 vg_settings
.windowed_before
[2],
228 vg_settings
.windowed_before
[3] );
229 SDL_SetWindowPosition( vg
.window
,
230 vg_settings
.windowed_before
[0],
231 vg_settings
.windowed_before
[1] );
232 SDL_SetWindowResizable( vg
.window
, SDL_TRUE
);
236 vg
.fps_limit
= vg_settings
.fps_limit
.new_value
;
237 vg
.quality_profile
= vg_settings
.quality
.new_value
;
238 vg
.vsync
= vg_settings
.vsync
.new_value
;
241 static void aaaaaaaaaaaaaaaaa( ui_rect r
);
242 static void vg_settings_video_gui( ui_rect panel
){
245 ui_standard_widget( panel
, rq
, 1 );
246 vg_settings_enum( &vg_settings
.quality
, rq
);
250 if( vg
.vsync_feature
== k_vsync_feature_error
){
251 ui_info( panel
, "There was an error activating vsync feature." );
256 vg_settings_ui_header( panel
, "Frame Timing" );
258 ui_standard_widget( panel
, duo
, 1 );
259 ui_split_ratio( duo
, k_ui_axis_v
, 0.5f
, 16, d0
, d1
);
261 vg_settings_enum( &vg_settings
.vsync
, d0
);
262 validated
&= vg_settings_ui_ranged_i32( &vg_settings
.fps_limit
, d1
);
264 ui_standard_widget( panel
, duo
, 10 );
265 aaaaaaaaaaaaaaaaa( duo
);
268 vg_settings_ui_header( panel
, "Window Specification" );
270 ui_standard_widget( panel
, duo
, 1 );
271 vg_settings_enum( &vg_settings
.screenmode
, duo
);
273 if( vg_settings_apply_button( panel
, validated
) )
274 vg_settings_video_apply();
277 static void vg_settings_audio_apply(void){
278 if( vg_settings_enum_diff( &vg_settings
.audio_devices
) ){
279 if( vg_audio
.sdl_output_device
){
280 vg_info( "Closing audio device %d\n", vg_audio
.sdl_output_device
);
281 SDL_CloseAudioDevice( vg_audio
.sdl_output_device
);
284 vg_strfree( &vg_audio
.device_choice
);
286 if( vg_settings
.audio_devices
.new_value
== -1 ){ }
287 else if( vg_settings
.audio_devices
.new_value
== -2 ){
288 vg_fatal_error( "Programming error\n" );
291 struct ui_enum_opt
*selected
= NULL
, *oi
;
293 for( int i
=0; i
<vg_settings
.audio_devices
.option_count
; i
++ ){
294 oi
= &vg_settings
.audio_devices
.options
[i
];
296 if( oi
->value
== vg_settings
.audio_devices
.new_value
){
302 vg_strnull( &vg_audio
.device_choice
, NULL
, -1 );
303 vg_strcat( &vg_audio
.device_choice
, oi
->alias
);
306 vg_audio_device_init();
307 *vg_settings
.audio_devices
.actual_value
=
308 vg_settings
.audio_devices
.new_value
;
312 if( vg_settings_enum_diff( &vg_settings
.dsp
) ){
313 *vg_settings
.dsp
.actual_value
=
314 vg_settings
.dsp
.new_value
;
320 static void vg_settings_audio_gui( ui_rect panel
){
322 ui_standard_widget( panel
, rq
, 1 );
323 vg_settings_enum( &vg_settings
.audio_devices
, rq
);
325 ui_standard_widget( panel
, rq
, 1 );
326 vg_settings_enum( &vg_settings
.dsp
, rq
);
328 if( vg_settings_apply_button( panel
, 1 ) )
329 vg_settings_audio_apply();
332 static void vg_settings_open(void){
333 vg
.settings_open
= 1;
335 ui_settings_ranged_i32_init( &vg_settings
.fps_limit
);
336 ui_settings_enum_init( &vg_settings
.vsync
);
337 ui_settings_enum_init( &vg_settings
.quality
);
338 ui_settings_enum_init( &vg_settings
.screenmode
);
340 /* Create audio options */
341 int count
= SDL_GetNumAudioDevices( 0 );
343 struct ui_enum_opt
*options
= malloc( sizeof(struct ui_enum_opt
)*(count
+1) );
344 vg_settings
.audio_devices
.options
= options
;
345 vg_settings
.audio_devices
.option_count
= count
+1;
347 struct ui_enum_opt
*o0
= &options
[0];
348 o0
->alias
= "OS Default";
351 for( int i
=0; i
<count
; i
++ ){
352 struct ui_enum_opt
*oi
= &options
[i
+1];
354 const char *device_name
= SDL_GetAudioDeviceName( i
, 0 );
355 int len
= strlen(device_name
);
357 oi
->alias
= malloc( len
+1 );
358 memcpy( (void *)oi
->alias
, device_name
, len
+1 );
362 if( vg_audio
.device_choice
.buffer
){
363 vg_settings
.temp_audio_choice
= -2;
365 for( int i
=0; i
<count
; i
++ ){
366 struct ui_enum_opt
*oi
= &options
[i
+1];
367 if( !strcmp( oi
->alias
, vg_audio
.device_choice
.buffer
) ){
368 vg_settings
.temp_audio_choice
= oi
->value
;
374 vg_settings
.temp_audio_choice
= -1;
377 ui_settings_enum_init( &vg_settings
.audio_devices
);
378 ui_settings_enum_init( &vg_settings
.dsp
);
380 #ifdef VG_GAME_SETTINGS
381 vg_game_settings_init();
385 static void vg_settings_close(void){
386 vg
.settings_open
= 0;
388 struct ui_enum_opt
*options
= vg_settings
.audio_devices
.options
;
389 for( int i
=1; i
< vg_settings
.audio_devices
.option_count
; i
++ )
390 free( (void *)options
[i
].alias
);
391 free( vg_settings
.audio_devices
.options
);
394 static void vg_settings_gui(void){
396 ui_rect screen
= { 0, 0, vg
.window_x
, vg
.window_y
};
397 ui_rect window
= { 0, 0, 1000, 700 };
398 ui_rect_center( screen
, window
);
399 vg_ui
.wants_mouse
= 1;
401 ui_fill( window
, ui_colour( k_ui_bg
+1 ) );
402 ui_outline( window
, 1, ui_colour( k_ui_bg
+7 ), 0 );
404 ui_rect title
, panel
;
405 ui_split( window
, k_ui_axis_h
, 28, 0, title
, panel
);
406 ui_fill( title
, ui_colour( k_ui_bg
+7 ) );
407 ui_text( title
, "Settings", 1, k_ui_align_middle_center
,
408 ui_colourcont(k_ui_bg
+7) );
411 ui_split( title
, k_ui_axis_v
, title
[2]-title
[3], 2, title
, quit_button
);
413 if( ui_button_text( quit_button
, "X", 1 ) == 1 ){
418 ui_rect_pad( panel
, (ui_px
[2]){ 8, 8 } );
420 const char *opts
[] = { "video", "audio",
421 #ifdef VG_GAME_SETTINGS
427 ui_tabs( panel
, panel
, opts
, vg_list_size(opts
), &page
);
430 vg_settings_video_gui( panel
);
433 vg_settings_audio_gui( panel
);
435 #ifdef VG_GAME_SETTINGS
437 vg_game_settings_gui( panel
);
441 static int cmd_vg_settings_toggle( int argc
, const char *argv
[] ){
446 #endif /* VG_SETTINGS_MENU_H */