1 #ifndef VG_SETTINGS_MENU_H
2 #define VG_SETTINGS_MENU_H
7 struct ui_enum_opt vg_settings_vsync_enum
[] = {
13 struct ui_enum_opt vg_settings_quality_enum
[] = {
14 { 0, "High Quality" },
16 { 2, "Absolute Minimum" },
19 struct ui_enum_opt vg_settings_screen_mode_enum
[] = {
20 { 0, "Fullscreen (desktop)" },
21 { 1, "Fullscreen (native)" },
22 { 2, "Floating Window" }
26 struct vg_setting_ranged_i32
{
27 i32 new_value
, *actual_value
, min
, max
;
33 struct vg_setting_enum
{
34 i32 new_value
, *actual_value
;
36 struct ui_enum_opt
*options
;
40 vsync
, quality
, screenmode
, audio_devices
;
41 i32 temp_audio_choice
;
43 int windowed_before
[4];
45 static vg_settings
= {
46 .fps_limit
= { .label
= "Fps Limit",
47 .min
=24, .max
=300, .actual_value
= &vg
.fps_limit
},
48 .vsync
= { .label
= "Vsync",
49 .actual_value
= &vg
.vsync
,
50 .options
= vg_settings_vsync_enum
, .option_count
= 3 },
51 .quality
= { .label
= "Graphic Quality",
52 .actual_value
= &vg
.quality_profile
,
53 .options
= vg_settings_quality_enum
, .option_count
= 3 },
54 .screenmode
= { .label
= "Type",
55 .actual_value
= &vg
.screen_mode
,
56 .options
= vg_settings_screen_mode_enum
, .option_count
=3 },
57 .audio_devices
= { .label
= "Audio Device",
58 .actual_value
= &vg_settings
.temp_audio_choice
,
59 .options
= NULL
, .option_count
= 0 }
62 static void vg_settings_ui_draw_diff( ui_rect orig
){
64 ui_split( orig
, k_ui_axis_v
, -32, 0, l
, r
);
65 ui_text( r
, "*", 1, k_ui_align_middle_center
, ui_colour(k_ui_blue
) );
69 * ------------------------------------------------------------------------- */
71 static void vg_settings_ui_int( char *buf
, u32 len
){
72 for( u32 i
=0, j
=0; i
<len
; i
++ ){
73 if( ((buf
[i
] >= '0') && (buf
[i
] <= '9')) || (buf
[i
] == '\0') )
78 struct ui_textbox_callbacks
static vg_settings_ui_int_callbacks
= {
79 .change
= vg_settings_ui_int
82 static bool vg_settings_ranged_i32_valid( struct vg_setting_ranged_i32
*prop
){
83 if( prop
->new_value
< prop
->min
) return 0;
84 if( prop
->new_value
> prop
->max
) return 0;
88 static bool vg_settings_ranged_i32_diff( struct vg_setting_ranged_i32
*prop
){
89 if( prop
->new_value
!= *prop
->actual_value
) return 1;
93 static bool vg_settings_ui_ranged_i32( struct vg_setting_ranged_i32
*prop
,
96 rect_copy( rect
, orig
);
98 ui_textbox( rect
, prop
->label
, prop
->buf
, sizeof(prop
->buf
),
99 1, 0, &vg_settings_ui_int_callbacks
);
100 prop
->new_value
= atoi( prop
->buf
);
102 if( vg_settings_ranged_i32_diff( prop
) )
103 vg_settings_ui_draw_diff( orig
);
105 bool valid
= vg_settings_ranged_i32_valid( prop
);
108 ui_split( orig
, k_ui_axis_h
, -1, 0, _null
, line
);
111 ui_fill( line
, ui_colour( k_ui_red
) );
117 static void ui_settings_ranged_i32_init( struct vg_setting_ranged_i32
*prop
){
119 vg_strnull( &tmp
, prop
->buf
, sizeof(prop
->buf
) );
120 vg_strcati32( &tmp
, *prop
->actual_value
);
121 prop
->new_value
= *prop
->actual_value
;
125 * ------------------------------------------------------------------------- */
127 static bool vg_settings_enum_diff( struct vg_setting_enum
*prop
){
128 if( prop
->new_value
!= *prop
->actual_value
) return 1;
132 static bool vg_settings_enum( struct vg_setting_enum
*prop
, ui_rect rect
){
134 rect_copy( rect
, orig
);
136 ui_enum( rect
, prop
->label
,
137 prop
->options
, prop
->option_count
, &prop
->new_value
);
139 if( vg_settings_enum_diff( prop
) )
140 vg_settings_ui_draw_diff( orig
);
145 static void ui_settings_enum_init( struct vg_setting_enum
*prop
){
146 prop
->new_value
= *prop
->actual_value
;
151 static void vg_settings_ui_header( ui_rect inout_panel
, const char *name
){
153 ui_standard_widget( inout_panel
, rect
, 2 );
154 ui_text( rect
, name
, 1, k_ui_align_middle_center
, ui_colour(k_ui_fg
+3) );
157 static void vg_settings_video_apply(void){
158 if( vg_settings_enum_diff( &vg_settings
.screenmode
) ){
159 vg
.screen_mode
= vg_settings
.screenmode
.new_value
;
161 if( (vg
.screen_mode
== 0) || (vg
.screen_mode
== 1) ){
162 SDL_GetWindowPosition( vg
.window
,
163 &vg_settings
.windowed_before
[0],
164 &vg_settings
.windowed_before
[1] );
165 vg_settings
.windowed_before
[2] = vg
.window_x
;
166 vg_settings
.windowed_before
[3] = vg
.window_y
;
168 SDL_DisplayMode video_mode
;
169 if( SDL_GetDesktopDisplayMode( 0, &video_mode
) ){
170 vg_error("SDL_GetDesktopDisplayMode failed: %s\n", SDL_GetError());
173 //vg.display_refresh_rate = video_mode.refresh_rate;
174 vg
.window_x
= video_mode
.w
;
175 vg
.window_y
= video_mode
.h
;
177 SDL_SetWindowResizable( vg
.window
, SDL_FALSE
);
178 SDL_SetWindowSize( vg
.window
, vg
.window_x
, vg
.window_y
);
181 if( vg
.screen_mode
== 0 )
182 SDL_SetWindowFullscreen( vg
.window
, SDL_WINDOW_FULLSCREEN_DESKTOP
);
183 if( vg
.screen_mode
== 1 )
184 SDL_SetWindowFullscreen( vg
.window
, SDL_WINDOW_FULLSCREEN
);
185 if( vg
.screen_mode
== 2 ){
186 SDL_SetWindowFullscreen( vg
.window
, 0 );
187 SDL_SetWindowSize( vg
.window
,
188 vg_settings
.windowed_before
[2],
189 vg_settings
.windowed_before
[3] );
190 SDL_SetWindowPosition( vg
.window
,
191 vg_settings
.windowed_before
[0],
192 vg_settings
.windowed_before
[1] );
193 SDL_SetWindowResizable( vg
.window
, SDL_TRUE
);
197 vg
.fps_limit
= vg_settings
.fps_limit
.new_value
;
198 vg
.quality_profile
= vg_settings
.quality
.new_value
;
199 vg
.vsync
= vg_settings
.vsync
.new_value
;
202 static void aaaaaaaaaaaaaaaaa( ui_rect r
);
203 static void vg_settings_video_gui( ui_rect panel
){
206 ui_standard_widget( panel
, rq
, 1 );
207 vg_settings_enum( &vg_settings
.quality
, rq
);
211 if( vg
.vsync_feature
== k_vsync_feature_error
){
212 ui_info( panel
, "There was an error activating vsync feature." );
217 vg_settings_ui_header( panel
, "Frame Timing" );
219 ui_standard_widget( panel
, duo
, 1 );
220 ui_split_ratio( duo
, k_ui_axis_v
, 0.5f
, 16, d0
, d1
);
222 vg_settings_enum( &vg_settings
.vsync
, d0
);
223 validated
&= vg_settings_ui_ranged_i32( &vg_settings
.fps_limit
, d1
);
225 ui_standard_widget( panel
, duo
, 10 );
226 aaaaaaaaaaaaaaaaa( duo
);
229 vg_settings_ui_header( panel
, "Window Specification" );
231 ui_standard_widget( panel
, duo
, 1 );
232 vg_settings_enum( &vg_settings
.screenmode
, duo
);
236 ui_px height
= (vg_ui
.font
->glyph_height
+ 18) * k_ui_scale
;
237 ui_split( panel
, k_ui_axis_h
, -height
, k_ui_padding
,
240 const char *string
= "Apply";
242 if( ui_button( last_row
, string
) == 1 )
243 vg_settings_video_apply();
247 ui_standard_widget( last_row
, rect
, 1 );
248 ui_fill( rect
, ui_colour( k_ui_bg
+1 ) );
249 ui_outline( rect
, -1, ui_colour( k_ui_red
), 0 );
251 ui_rect t
= { 0,0, ui_text_line_width( string
), 14 };
252 ui_rect_center( rect
, t
);
253 ui_text( t
, string
, 1, k_ui_align_left
, ui_colour(k_ui_fg
+3) );
257 static void vg_settings_audio_apply(void){
258 if( vg_settings_enum_diff( &vg_settings
.audio_devices
) ){
259 if( vg_audio
.sdl_output_device
){
260 vg_info( "Closing audio device %d\n", vg_audio
.sdl_output_device
);
261 SDL_CloseAudioDevice( vg_audio
.sdl_output_device
);
264 if( vg_audio
.force_device_name
){
265 free( vg_audio
.force_device_name
);
266 vg_audio
.force_device_name
= NULL
;
269 if( vg_settings
.audio_devices
.new_value
== -1 ){ }
270 else if( vg_settings
.audio_devices
.new_value
== -2 ){
271 vg_fatal_error( "Programming error\n" );
274 struct ui_enum_opt
*selected
= NULL
, *oi
;
276 for( int i
=0; i
<vg_settings
.audio_devices
.option_count
; i
++ ){
277 oi
= &vg_settings
.audio_devices
.options
[i
];
279 if( oi
->value
== vg_settings
.audio_devices
.new_value
){
285 int len
= strlen(oi
->alias
);
286 vg_audio
.force_device_name
= malloc(len
+1);
287 memcpy( vg_audio
.force_device_name
, (void *)oi
->alias
, len
+1 );
290 vg_audio_device_init();
291 *vg_settings
.audio_devices
.actual_value
=
292 vg_settings
.audio_devices
.new_value
;
296 static void vg_settings_audio_gui( ui_rect panel
){
298 ui_standard_widget( panel
, rq
, 1 );
299 vg_settings_enum( &vg_settings
.audio_devices
, rq
);
301 const char *string
= "Apply";
304 ui_px height
= (vg_ui
.font
->glyph_height
+ 18) * k_ui_scale
;
305 ui_split( panel
, k_ui_axis_h
, -height
, k_ui_padding
,
308 if( ui_button( last_row
, string
) == 1 )
309 vg_settings_audio_apply();
312 static void vg_settings_open(void){
313 vg
.settings_open
= 1;
315 ui_settings_ranged_i32_init( &vg_settings
.fps_limit
);
316 ui_settings_enum_init( &vg_settings
.vsync
);
317 ui_settings_enum_init( &vg_settings
.quality
);
318 ui_settings_enum_init( &vg_settings
.screenmode
);
320 /* Create audio options */
321 int count
= SDL_GetNumAudioDevices( 0 );
323 struct ui_enum_opt
*options
= malloc( sizeof(struct ui_enum_opt
)*(count
+1) );
324 vg_settings
.audio_devices
.options
= options
;
325 vg_settings
.audio_devices
.option_count
= count
+1;
327 struct ui_enum_opt
*o0
= &options
[0];
328 o0
->alias
= "OS Default";
331 for( int i
=0; i
<count
; i
++ ){
332 struct ui_enum_opt
*oi
= &options
[i
+1];
334 const char *device_name
= SDL_GetAudioDeviceName( i
, 0 );
335 int len
= strlen(device_name
);
337 oi
->alias
= malloc( len
+1 );
338 memcpy( (void *)oi
->alias
, device_name
, len
+1 );
342 if( vg_audio
.force_device_name
){
343 vg_settings
.temp_audio_choice
= -2;
345 for( int i
=0; i
<count
; i
++ ){
346 struct ui_enum_opt
*oi
= &options
[i
+1];
347 if( !strcmp( oi
->alias
, vg_audio
.force_device_name
) ){
348 vg_settings
.temp_audio_choice
= oi
->value
;
354 vg_settings
.temp_audio_choice
= -1;
357 ui_settings_enum_init( &vg_settings
.audio_devices
);
360 static void vg_settings_close(void){
361 vg
.settings_open
= 0;
363 struct ui_enum_opt
*options
= vg_settings
.audio_devices
.options
;
364 for( int i
=1; i
< vg_settings
.audio_devices
.option_count
; i
++ )
365 free( (void *)options
[i
].alias
);
366 free( vg_settings
.audio_devices
.options
);
369 static void vg_settings_gui(void){
371 ui_rect screen
= { 0, 0, vg
.window_x
, vg
.window_y
};
372 ui_rect window
= { 0, 0, 1000, 700 };
373 ui_rect_center( screen
, window
);
374 vg_ui
.wants_mouse
= 1;
376 ui_fill( window
, ui_colour( k_ui_bg
+1 ) );
377 ui_outline( window
, 1, ui_colour( k_ui_bg
+7 ), 0 );
379 ui_rect title
, panel
;
380 ui_split( window
, k_ui_axis_h
, 28, 0, title
, panel
);
381 ui_fill( title
, ui_colour( k_ui_bg
+7 ) );
382 ui_text( title
, "Settings", 1, k_ui_align_middle_center
,
383 ui_colourcont(k_ui_bg
+7) );
386 ui_split( title
, k_ui_axis_v
, title
[2]-title
[3], 2, title
, quit_button
);
388 if( ui_button_text( quit_button
, "X", 1 ) == 1 ){
393 ui_rect_pad( panel
, (ui_px
[2]){ 8, 8 } );
396 ui_tabs( panel
, panel
, (const char *[]){ "video", "audio", "game" },
400 vg_settings_video_gui( panel
);
403 vg_settings_audio_gui( panel
);
406 static int cmd_vg_settings_toggle( int argc
, const char *argv
[] ){
411 #endif /* VG_SETTINGS_MENU_H */