64 bit fract function
[vg.git] / vg_settings_menu.h
index 96fc6ea4725ff4bf0e433175ffcd456dc0b25655..7198810bb9c1324cc1a37f5af6c557067cfd33fe 100644 (file)
@@ -4,6 +4,11 @@
 #include "vg.h"
 #include "vg_imgui.h"
 
+#ifdef VG_GAME_SETTINGS
+static void vg_game_settings_gui( ui_rect panel ) ;
+static void vg_game_settings_init(void);
+#endif 
+
 struct ui_enum_opt vg_settings_vsync_enum[] = { 
    { 0, "None" },
    { 1, "On" },
@@ -22,6 +27,11 @@ struct ui_enum_opt vg_settings_screen_mode_enum[] = {
    { 2, "Floating Window" }
 };
 
+struct ui_enum_opt vg_settings_dsp_enum[] = {
+   { 1, "Enabled" },
+   { 0, "Disabled" },
+};
+
 struct {
    struct vg_setting_ranged_i32{
       i32 new_value, *actual_value, min, max;
@@ -37,9 +47,8 @@ struct {
       u32 option_count;
       const char *label;
    }
-   vsync, quality, screenmode;
-
-   int windowed_before[4];
+   vsync, quality, screenmode, audio_devices, dsp;
+   i32 temp_audio_choice;
 }
 static vg_settings = {
    .fps_limit =   { .label = "Fps Limit",
@@ -52,8 +61,13 @@ static vg_settings = {
                      .options = vg_settings_quality_enum, .option_count = 3 },
    .screenmode =  { .label = "Type",
                      .actual_value = &vg.screen_mode,
-                     .options = vg_settings_screen_mode_enum, .option_count=3 }
-
+                     .options = vg_settings_screen_mode_enum, .option_count=3 },
+   .audio_devices = { .label = "Audio Device",
+                      .actual_value = &vg_settings.temp_audio_choice,
+                      .options = NULL, .option_count = 0 },
+   .dsp = { .label = "Audio effects (reverb etc.)",
+             .actual_value = &vg_audio.dsp_enabled,
+             .options = vg_settings_dsp_enum, .option_count=2 },
 };
 
 static void vg_settings_ui_draw_diff( ui_rect orig ){
@@ -151,17 +165,37 @@ static void vg_settings_ui_header( ui_rect inout_panel, const char *name ){
    ui_text( rect, name, 1, k_ui_align_middle_center, ui_colour(k_ui_fg+3) );
 }
 
+
+static bool vg_settings_apply_button( ui_rect inout_panel, bool validated ){
+   ui_rect last_row;
+   ui_px height = (vg_ui.font->glyph_height + 18) * k_ui_scale;
+   ui_split( inout_panel, k_ui_axis_h, -height, k_ui_padding, 
+             inout_panel, last_row );
+
+   const char *string = "Apply";
+   if( validated ){
+      if( ui_button( last_row, string ) == 1 )
+         return 1;
+   }
+   else{
+      ui_rect rect;
+      ui_standard_widget( last_row, rect, 1 );
+      ui_fill( rect, ui_colour( k_ui_bg+1 ) );
+      ui_outline( rect, -1, ui_colour( k_ui_red ), 0 );
+
+      ui_rect t = { 0,0, ui_text_line_width( string ), 14 };
+      ui_rect_center( rect, t );
+      ui_text( t, string, 1, k_ui_align_left, ui_colour(k_ui_fg+3) );
+   }
+
+   return 0;
+}
+
 static void vg_settings_video_apply(void){
    if( vg_settings_enum_diff( &vg_settings.screenmode ) ){
       vg.screen_mode = vg_settings.screenmode.new_value;
 
       if( (vg.screen_mode == 0) || (vg.screen_mode == 1) ){
-         SDL_GetWindowPosition( vg.window, 
-                                &vg_settings.windowed_before[0],
-                                &vg_settings.windowed_before[1] );
-         vg_settings.windowed_before[2] = vg.window_x;
-         vg_settings.windowed_before[3] = vg.window_y;
-
          SDL_DisplayMode video_mode;
          if( SDL_GetDesktopDisplayMode( 0, &video_mode ) ){
             vg_error("SDL_GetDesktopDisplayMode failed: %s\n", SDL_GetError());
@@ -171,7 +205,6 @@ static void vg_settings_video_apply(void){
             vg.window_x = video_mode.w;
             vg.window_y = video_mode.h;
          }
-         SDL_SetWindowResizable( vg.window, SDL_FALSE );
          SDL_SetWindowSize( vg.window, vg.window_x, vg.window_y );
       }
 
@@ -181,13 +214,10 @@ static void vg_settings_video_apply(void){
          SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN );
       if( vg.screen_mode == 2 ){
          SDL_SetWindowFullscreen( vg.window, 0 );
-         SDL_SetWindowSize( vg.window, 
-                            vg_settings.windowed_before[2],
-                            vg_settings.windowed_before[3] );
-         SDL_SetWindowPosition( vg.window, 
-                                vg_settings.windowed_before[0],
-                                vg_settings.windowed_before[1] );
-         SDL_SetWindowResizable( vg.window, SDL_TRUE );
+         SDL_SetWindowSize( vg.window, 1280, 720 );
+         SDL_SetWindowPosition( vg.window, 16, 16 );
+         SDL_SetWindowMinimumSize( vg.window, 1280, 720 );
+         SDL_SetWindowMaximumSize( vg.window, 4096, 4096 );
       }
    }
 
@@ -228,27 +258,125 @@ static void vg_settings_video_gui( ui_rect panel ){
    ui_standard_widget( panel, duo, 1 );
    vg_settings_enum( &vg_settings.screenmode, duo );
 
-   /* apply */
-   ui_rect last_row;
-   ui_px height = (vg_ui.font->glyph_height + 18) * k_ui_scale;
-   ui_split( panel, k_ui_axis_h, -height, k_ui_padding, 
-             panel, last_row );
+   if( vg_settings_apply_button( panel, validated ) )
+      vg_settings_video_apply();
+}
 
-   const char *string = "Apply";
-   if( validated ){
-      if( ui_button( last_row, string ) == 1 )
-         vg_settings_video_apply();
+static void vg_settings_audio_apply(void){
+   if( vg_settings_enum_diff( &vg_settings.audio_devices ) ){
+      if( vg_audio.sdl_output_device ){
+         vg_info( "Closing audio device %d\n", vg_audio.sdl_output_device );
+         SDL_CloseAudioDevice( vg_audio.sdl_output_device );
+      }
+      
+      vg_strfree( &vg_audio.device_choice );
+
+      if( vg_settings.audio_devices.new_value == -1 ){ }
+      else if( vg_settings.audio_devices.new_value == -2 ){
+         vg_fatal_error( "Programming error\n" );
+      }
+      else {
+         struct ui_enum_opt *selected = NULL, *oi;
+
+         for( int i=0; i<vg_settings.audio_devices.option_count; i ++ ){
+            oi = &vg_settings.audio_devices.options[i];
+
+            if( oi->value == vg_settings.audio_devices.new_value ){
+               selected = oi;
+               break;
+            }
+         }
+
+         vg_strnull( &vg_audio.device_choice, NULL, -1 );
+         vg_strcat( &vg_audio.device_choice, oi->alias );
+      }
+
+      vg_audio_device_init();
+      *vg_settings.audio_devices.actual_value = 
+         vg_settings.audio_devices.new_value;
    }
-   else{
-      ui_rect rect;
-      ui_standard_widget( last_row, rect, 1 );
-      ui_fill( rect, ui_colour( k_ui_bg+1 ) );
-      ui_outline( rect, -1, ui_colour( k_ui_red ), 0 );
 
-      ui_rect t = { 0,0, ui_text_line_width( string ), 14 };
-      ui_rect_center( rect, t );
-      ui_text( t, string, 1, k_ui_align_left, ui_colour(k_ui_fg+3) );
+   audio_lock();
+   if( vg_settings_enum_diff( &vg_settings.dsp ) ){
+      *vg_settings.dsp.actual_value =
+         vg_settings.dsp.new_value;
    }
+
+   audio_unlock();
+}
+
+static void vg_settings_audio_gui( ui_rect panel ){
+   ui_rect rq;
+   ui_standard_widget( panel, rq, 1 );
+   vg_settings_enum( &vg_settings.audio_devices, rq );
+   
+   ui_standard_widget( panel, rq, 1 );
+   vg_settings_enum( &vg_settings.dsp, rq );
+
+   if( vg_settings_apply_button( panel, 1 ) )
+      vg_settings_audio_apply();
+}
+
+static void vg_settings_open(void){
+   vg.settings_open = 1;
+
+   ui_settings_ranged_i32_init( &vg_settings.fps_limit );
+   ui_settings_enum_init( &vg_settings.vsync );
+   ui_settings_enum_init( &vg_settings.quality );
+   ui_settings_enum_init( &vg_settings.screenmode );
+   
+   /* Create audio options */
+   int count = SDL_GetNumAudioDevices( 0 );
+
+   struct ui_enum_opt *options = malloc( sizeof(struct ui_enum_opt)*(count+1) );
+   vg_settings.audio_devices.options = options;
+   vg_settings.audio_devices.option_count = count+1;
+
+   struct ui_enum_opt *o0 = &options[0];
+   o0->alias = "OS Default";
+   o0->value = -1;
+
+   for( int i=0; i<count; i ++ ){
+      struct ui_enum_opt *oi = &options[i+1];
+
+      const char *device_name = SDL_GetAudioDeviceName( i, 0 );
+      int len = strlen(device_name);
+
+      oi->alias = malloc( len+1 );
+      memcpy( (void *)oi->alias, device_name, len+1 );
+      oi->value = i;
+   }
+
+   if( vg_audio.device_choice.buffer ){
+      vg_settings.temp_audio_choice = -2;
+
+      for( int i=0; i<count; i ++ ){
+         struct ui_enum_opt *oi = &options[i+1];
+         if( !strcmp( oi->alias, vg_audio.device_choice.buffer ) ){
+            vg_settings.temp_audio_choice = oi->value;
+            break;
+         }
+      }
+   }
+   else {
+      vg_settings.temp_audio_choice = -1;
+   }
+
+   ui_settings_enum_init( &vg_settings.audio_devices );
+   ui_settings_enum_init( &vg_settings.dsp );
+
+#ifdef VG_GAME_SETTINGS
+   vg_game_settings_init();
+#endif
+}
+
+static void vg_settings_close(void){
+   vg.settings_open = 0;
+
+   struct ui_enum_opt *options = vg_settings.audio_devices.options;
+   for( int i=1; i < vg_settings.audio_devices.option_count; i ++ )
+      free( (void *)options[i].alias );
+   free( vg_settings.audio_devices.options );
 }
 
 static void vg_settings_gui(void){
@@ -271,30 +399,35 @@ static void vg_settings_gui(void){
    ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button );
 
    if( ui_button_text( quit_button, "X", 1 ) == 1 ){
-      vg.settings_open = 0;
+      vg_settings_close();
       return;
    }
 
    ui_rect_pad( panel, (ui_px[2]){ 8, 8 } );
    
+   const char *opts[] = { "video", "audio",
+#ifdef VG_GAME_SETTINGS
+   "game"
+#endif
+   };
+
    static i32 page = 0;
-   ui_tabs( panel, panel, (const char *[]){ "video", "audio", "game" }, 
-            3, &page );
+   ui_tabs( panel, panel, opts, vg_list_size(opts), &page );
 
    if( page == 0 ){
       vg_settings_video_gui( panel );
    }
+   else if( page == 1 )
+      vg_settings_audio_gui( panel );
+
+#ifdef VG_GAME_SETTINGS
+   else if( page == 2 )
+      vg_game_settings_gui( panel );
+#endif
 }
 
 static int cmd_vg_settings_toggle( int argc, const char *argv[] ){
-   vg.settings_open = !vg.settings_open;
-
-   if( vg.settings_open ){
-      ui_settings_ranged_i32_init( &vg_settings.fps_limit );
-      ui_settings_enum_init( &vg_settings.vsync );
-      ui_settings_enum_init( &vg_settings.quality );
-      ui_settings_enum_init( &vg_settings.screenmode );
-   }
+   vg_settings_open();
    return 0;
 }