fully ported to vg2
authorhgn <hgodden00@gmail.com>
Thu, 4 Jan 2024 13:13:38 +0000 (13:13 +0000)
committerhgn <hgodden00@gmail.com>
Thu, 4 Jan 2024 13:23:31 +0000 (13:23 +0000)
fishladder_resources_vg1.h
fishladder_vg1.c
marblecomp.c
marblecomp_settings.h [new file with mode: 0644]
steam.h [new file with mode: 0644]

index 7d0ea2fc7c69bb016dce114add3fd48e4b6dc107..df93a501eaed57e86efebaa574dca7628710e021 100644 (file)
@@ -128,15 +128,6 @@ audio_clip audio_music[] = {
    { .path="sound/mccompt2.ogg" },
 };
 
-#if 0
-static void *load_and_play_bgm( void *_inf )
-{
-   sfx_set_init( &audio_music, NULL );
-   sfx_set_play( &audio_music, &audio_system_music, 0 );
-   return NULL;
-}
-#endif
-
 #define INIT_AUDIO( X ) audio_clip_loadn( X, vg_list_size(X), NULL );
 
 static void _mc_resource_load_main(void){
@@ -154,10 +145,7 @@ static void _mc_resource_load_main(void){
        INIT_AUDIO( audio_random );
        INIT_AUDIO( audio_clicks );
        INIT_AUDIO( audio_tones );
-
-#if 0
-   vg_thread_run( load_and_play_bgm, NULL );
-#endif
+   INIT_AUDIO( audio_music );
 }
 
 /*
index 6eb55341d3bfb21649c040188dfaeae72e33955c..d58d229acd8603b9070f5fbda364185394d5b0e9 100644 (file)
@@ -373,19 +373,6 @@ m3x3f m_projection;
 m3x3f m_view;
 m3x3f m_mdl;
 
-static int colour_set_id = 0;
-static int world_theme_id = 0;
-static int enable_bloom = 1;
-static int enable_vignette = 1;
-static float music_volume = 1.0f;
-
-static void music_volume_update(void)
-{
-#if 0
-   sfx_vol_fset( &audio_volume_music, music_volume );
-#endif
-}
-
 static v3f colour_sets[][4] =
 {
        { { 1.0f, 0.9f, 0.3f },
@@ -431,11 +418,9 @@ world_themes[] =
    }
 };
 
-static void colour_code_v3( i8 cc, v3f target )
-{
-   if( (cc >= 0) && (cc < vg_list_size( colour_sets[0] )) )
-   {
-      v3_copy( colour_sets[colour_set_id][ cc ], target );
+static void colour_code_v3( i8 cc, v3f target ){
+   if( (cc >= 0) && (cc < vg_list_size( colour_sets[0] )) ){
+      v3_copy( colour_sets[marblecomp.colour_set][ cc ], target );
       return;
    }
        
@@ -1413,7 +1398,6 @@ static void career_pass_level( struct cmp_level *lvl, int score, int upload )
                if( lvl->unlock ) 
          career_unlock_level( lvl->unlock );
                
-               #ifdef VG_STEAM
                if( lvl->achievement )
                        sw_set_achievement( lvl->achievement );
 
@@ -1430,7 +1414,6 @@ static void career_pass_level( struct cmp_level *lvl, int score, int upload )
                }
                
                sw_set_achievement( "MASTER_ENGINEER" );
-               #endif
        }
 }
 
@@ -2133,9 +2116,7 @@ static void _mc_vg1_update(void)
                                                        if( cell_entry->config == k_cell_type_con_r || cell_entry->config == k_cell_type_con_u 
                                                                || cell_entry->config == k_cell_type_con_l || cell_entry->config == k_cell_type_con_d )
                                                        {
-                                                               #ifdef VG_STEAM
                                                                sw_set_achievement( "CAN_DO_THAT" );
-                                                               #endif
 
                                                                fish->state = k_fish_state_soon_alive;
                                                                
@@ -2254,9 +2235,7 @@ static void _mc_vg1_update(void)
                                                        
                                                        if( collide_next_frame || collide_this_frame )
                                                        {
-                                                               #ifdef VG_STEAM
                                                                sw_set_achievement( "BANG" );
-                                                               #endif
 
                                                                // Shatter death (+0.5s)
                                                                float death_time = world.sim_internal_time + ( collide_this_frame? 0.0f: 0.5f );
@@ -2401,10 +2380,8 @@ static void _mc_vg1_update(void)
                                }
                                else
                                {
-                                       #ifdef VG_STEAM
                                        if( world.sim_run > 0 )
                                                sw_set_achievement( "GOOD_ENOUGH" );
-                                       #endif
 
                                        vg_error( "Level failed :(\n" );
                                }
@@ -2778,7 +2755,7 @@ static void _mc_vg1_framebuffer_resize(int w, int h){
 }
 
 static void _mc_vg1_render(void){
-   if( enable_bloom || enable_vignette )
+   if( marblecomp.bloom || marblecomp.vignette )
       glBindFramebuffer( GL_FRAMEBUFFER, world.st.framebuffer );
    else
       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
@@ -2798,11 +2775,7 @@ static void _mc_vg1_render(void){
        int const empty_start = circle_base+32;
        int const empty_count = circle_base+32*2;
        
-#if 0
-   struct world_theme *theme = &world_themes[ world_theme_id ];
-#else
-   struct world_theme *theme = &world_themes[ 0 ];
-#endif
+   struct world_theme *theme = &world_themes[ marblecomp.world_theme ];
 
        if( !world.initialzed )
                return;
@@ -3091,10 +3064,11 @@ static void _mc_vg1_render(void){
                }
        }
 
-       if( world_button_exec( &world.st.buttons[k_world_button_settings], (v2f){ 1.0f, 2.0f }, btn_orange, &stat ))
+       if( world_button_exec( &world.st.buttons[k_world_button_settings], 
+                           (v2f){ 1.0f, 2.0f }, btn_orange, &stat ))
        {
-               world.st.state = stat == k_world_button_on_enable? 
-         k_game_state_settings: k_game_state_main;     
+      world.st.buttons[k_world_button_settings].state = 0;
+      vg_settings_open();
        }
 
        level_selection_buttons();
@@ -3499,9 +3473,8 @@ static void _mc_vg1_render(void){
        draw_numbers( (v3f){ 2.0f, (float)world.h-1.875f, 0.3333f }, world.score );
        */
    
-   if( !enable_bloom ) 
-   {
-      if( enable_vignette )
+   if( !marblecomp.bloom ){
+      if( marblecomp.vignette )
          goto image_composite;
 
       return;
@@ -3564,307 +3537,95 @@ image_composite:
    shader_post_comp_uTexBloom(1);
    
    shader_post_comp_uComp( (v2f){
-         enable_bloom? 1.0f: 0.0f,
-         enable_vignette? 0.0f: 1.0f
+         marblecomp.bloom? 1.0f: 0.0f,
+         marblecomp.vignette? 0.0f: 1.0f
    });
 
    draw_mesh( 0, 2 );
 }
 
 void _mc_vg1_ui(void) {
-   // Drawing world name
-#if 0
-   if( world.pCmpLevel )
-   {
-      gui_text( (ui_px [2]){ vg.window_x / 2, 4 }, world.pCmpLevel->title, 2, k_text_align_center );
-      gui_text( (ui_px [2]){ vg.window_x / 2, 28 }, world.pCmpLevel->description, 1, k_text_align_center );
-   }
-#endif
 
+   ui_px const unit_scale_px = 4*vg_ui.font->spacing;
+   
 #if 0
-   if( world.st.state == k_game_state_update )
-   {
-      gui_group_id( 34 );
+   if( world.pCmpLevel ){
+      for( int i = 0; i < vg_list_size( world.pCmpLevel->strings ); i ++ ){
+         struct world_string *wstr = &world.pCmpLevel->strings[i];
 
-      ui_global_ctx.cursor[2] = 458;
-      ui_global_ctx.cursor[3] = 316;
-      ui_global_ctx.cursor[0] = vg.window_x / 2 - 229;
-      ui_global_ctx.cursor[1] = vg.window_y / 2 - 158;
+         if( wstr->str ){
+            ui_px pos[2];
+            pos[0] = -vg_ui.font->spacing/2;
 
-      gui_new_node();
-      {
-         gui_capture_mouse( 200 );
-         gui_fill_rect( ui_global_ctx.cursor, 0xE8303030 );
-         
-         ui_px title_pos[2];
-         title_pos[0] = ui_global_ctx.cursor[0] + 229;
-         title_pos[1] = ui_global_ctx.cursor[1] + 16;
-
-         gui_text( title_pos, "Update 1.5", 2, k_text_align_center );
-
-         gui_text( (ui_px [2]){ ui_global_ctx.cursor[0] + 16, title_pos[1] + 45 },
-            "Welcome to the first update to marble computing!"
-            "\n"
-            "New features have been added:\n"
-            "\n"
-            "  - Settings menu\n"
-            "  - Map skins\n"
-            "  - More levels and a new block type\n"
-            "  - Scores for each level\n"
-            "  - Zooming and panning (mousewheel)\n"
-            "\n"
-            "There is much more in the works, such as a\n"
-            "soundtrack, and the rest of the levels for the\n"
-            "3 bit computer!\n"
-            "\n"
-            "Thank you everyone for enjoying my game :)\n",
-            1, k_text_align_left
-         );
-
-         ui_global_ctx.cursor[2] = 100;
-         ui_global_ctx.cursor[3] = 30;
-         ui_global_ctx.cursor[0] += 229 - 50;
-         ui_global_ctx.cursor[1] += 316 - 30 - 16;
-
-         if( gui_button( 1 ) )
-         {
-            world.st.state = k_game_state_main;
+            if( wstr->placement == k_placement_bottom )
+               pos[1] = 2*-unit_scale_px;
+            else
+               pos[1] = (world.h-1)*-unit_scale_px -6;
+
+            ui_text( &world.st.world_text, pos, wstr->str, 
+                  1, k_text_align_left );
          }
-         gui_text( (ui_px [2]){ ui_global_ctx.cursor[0] + 50,
-            ui_global_ctx.cursor[1] + 4 }, "OK", 1, k_text_align_center );
-         gui_end();
       }
-      gui_end();
    }
-   else 
 #endif
 
-#if 0
-   if( world.st.state == k_game_state_settings )
-       {
-               gui_group_id( 35 );
+   u32 sum = 0;
 
-               ui_global_ctx.cursor[2] = 225;
-               gui_fill_y();
-               gui_align_right();
-
-               gui_new_node();
-               {
-                       gui_capture_mouse( 200 );
-
-                       gui_fill_rect( ui_global_ctx.cursor, 0xC0202020 );
-                       ui_rect_pad( ui_global_ctx.cursor, 8 );
-                       
-                       ui_global_ctx.cursor[3] = 25;
-                       
-                       gui_new_node();
-                       {
-                               gui_text( ui_global_ctx.cursor, "SETTINGS", 2, 0 );
-
-            ui_global_ctx.cursor[2] = 25;
-            gui_align_right();
-            
-            if( gui_button(4) == k_button_click )
-            {
-               world.st.buttons[ k_world_button_settings ].state = 0;
-               world.st.state = k_game_state_main;
-               vg_info( "exit\n" );
-            }
-            ui_global_ctx.cursor[0] += 4;
-            ui_global_ctx.cursor[1] -= 4;
-            gui_text( ui_global_ctx.cursor, "x", 2, 0 );
-            gui_end();
-                       }
-                       gui_end();
-
-                       // Colour scheme selection
-                       ui_global_ctx.cursor[1] += 30;
-
-                       gui_text( ui_global_ctx.cursor, "Colour Scheme", 1, 0 );
-                       ui_global_ctx.cursor[1] += 25;
-
-                       gui_new_node();
-                       {
-                               ui_global_ctx.cursor[2] = 50;
-
-                               for( int i = 0; i < 4; i ++ )
-                               {
-                                       gui_new_node();
-                                       {
-                                               // Convert to RGB
-                                               u32 rgb = 0xff000000;
-
-                                               for( int j = 0; j < 3; j ++ )
-                                                       rgb |= (u32)(colour_sets[ colour_set_id ][i][j]*255.0f) << j * 8;
-
-                                               gui_fill_rect( ui_global_ctx.cursor, rgb );
-                                       }
-                                       gui_end_right();
-                               }
-                       }
-                       gui_end_down();
-                       
-                       gui_new_node();
-                       {
-                               ui_global_ctx.cursor[2] = 25;
-                               if( gui_button( 0 ) == k_button_click )
-                               {
-                                       if( colour_set_id > 0 )
-                                               colour_set_id --;
-                               }
-                               gui_text( ui_global_ctx.cursor, "<", 2, 0 );
-                               gui_end_right();
-                               
-                               ui_global_ctx.cursor[2] = 150;
-                               gui_new_node();
-                               {
-               gui_fill_rect( ui_global_ctx.cursor, 0x33ffffff );
-                                       gui_text( 
-                  (ui_px [2]){ ui_global_ctx.cursor[0] + 75, ui_global_ctx.cursor[1] + 6 }, 
-                  (const char *[]){ "Normal", "Extra1", "Extra2" }[ colour_set_id ], 
-                  1, k_text_align_center 
-               );
-                               }
-                               gui_end_right();
-
-                               ui_global_ctx.cursor[2] = 25;
-                               if( gui_button( 1 ) == k_button_click )
-                               {
-                                       if( colour_set_id < vg_list_size( colour_sets )-1 )
-                                               colour_set_id ++;
-                               }
-                               gui_text( ui_global_ctx.cursor, ">", 2, 0 );
-                               gui_end_down();
-                       }
-                       gui_end_down();
-
-         // Theme select
-         ui_global_ctx.cursor[1] += 16;
-
-#if 0
-                       gui_text( ui_global_ctx.cursor, "Tile Theme", 1, 0 );
-                       ui_global_ctx.cursor[1] += 20;
-
-                       gui_new_node();
-                       {
-                               ui_global_ctx.cursor[2] = 25;
-                               if( gui_button( 2 ) == k_button_click )
-                               {
-                                       if( world_theme_id > 0 )
-                                               world_theme_id --;
-                               }
-                               gui_text( ui_global_ctx.cursor, "<", 2, 0 );
-                               gui_end_right();
-                               
-                               ui_global_ctx.cursor[2] = 150;
-                               gui_new_node();
-                               {
-               gui_fill_rect( ui_global_ctx.cursor, 0x33ffffff );
-                                       gui_text( 
-                  (ui_px [2]){ ui_global_ctx.cursor[0] + 75, ui_global_ctx.cursor[1] + 6 },
-                  world_themes[ world_theme_id ].name, 1, k_text_align_center
-               );
-                               }
-                               gui_end_right();
-
-                               ui_global_ctx.cursor[2] = 25;
-                               if( gui_button( 3 ) == k_button_click )
-                               {
-                                       if( world_theme_id < vg_list_size( world_themes )-1 )
-                                               world_theme_id ++;
-                               }
-                               gui_text( ui_global_ctx.cursor, ">", 2, 0 );
-                               gui_end_down();
-                       }
-                       gui_end_down();
-#endif
-
-                       gui_text( ui_global_ctx.cursor, "Graphics", 1, 0 );
-                       ui_global_ctx.cursor[1] += 20;
-
-                       gui_new_node();
-                       {
-                               ui_global_ctx.cursor[2] = 200;
-                               if( gui_button( 5 ) == k_button_click )
-                               {
-               enable_bloom ^= 0x1;
-                               }
-            ui_global_ctx.cursor[0] += 4;
-            ui_global_ctx.cursor[1] += 4;
-                               gui_text( ui_global_ctx.cursor, enable_bloom? 
-                  "Bloom: ENABLED":
-                  "Bloom: DISABLED", 1, 0 );
-                               gui_end_down();
-                       }
-                       gui_end_down();
-
-                       ui_global_ctx.cursor[1] += 10;
-                       gui_new_node();
-                       {
-                               ui_global_ctx.cursor[2] = 200;
-                               if( gui_button( 6 ) == k_button_click )
-                               {
-               enable_vignette ^= 0x1;
-                               }
-            ui_global_ctx.cursor[0] += 4;
-            ui_global_ctx.cursor[1] += 4;
-                               gui_text( ui_global_ctx.cursor, enable_vignette? 
-                  "Vignette: ENABLED":
-                  "Vignette: DISABLED", 1, 0 );
-                               gui_end_down();
-                       }
-                       gui_end_down();
-
-                       ui_global_ctx.cursor[1] += 16;
-                       gui_text( ui_global_ctx.cursor, "Music Volume", 1, 0 );
-                       ui_global_ctx.cursor[1] += 20;
+   // re-create level scores
+   for( int i = 0; i < vg_list_size( career_packs ); i ++ ){
+      struct career_level_pack *set = &career_packs[i];
 
-                       gui_new_node();
-                       {
-            ui_px slider_start = ui_global_ctx.cursor[0];
-            
-            float const bar_width = 45.0f,
-                        bar_total = 200.0f,
-                        bar_movement = bar_total-bar_width,
-                        bar_start = bar_width * 0.5f;
-
-                               ui_global_ctx.cursor[2] = bar_total;
-            ui_fill_rect( &ui_global_ctx, 
-                          ui_global_ctx.cursor, 
-                          0xff111111 );
-
-                               ui_global_ctx.cursor[2] = bar_width;
-            ui_global_ctx.cursor[0] = slider_start + music_volume * bar_movement;
-            
-            int status = gui_button( 7 );
-            
-            static ui_px drag_start = 0.0f;
+      for( int j = 0; j < set->count; j ++ ){
+         struct cmp_level *lvl = &set->pack[j];
 
-            if( status == k_button_start_click )
-               drag_start = ui_global_ctx.mouse[0];
-            else if( ui_global_ctx.capture_lock && 
-                     (ui_global_ctx.capture_mouse_id == ui_group_id(&ui_global_ctx,7)))
-            {
-               ui_px drag_offset = ui_global_ctx.mouse[0] - drag_start;
-               float offset_local = (drag_start + drag_offset - slider_start - bar_start) / bar_movement;
+         if( lvl->completed_score && !lvl->is_tutorial ){
+            char num[10];
+            snprintf( num, 9, "%d", lvl->completed_score );
+            sum += lvl->completed_score;
+
+            v3f pos = {
+                    (f32)lvl->btn.position[0]+0.5f,
+                    (f32)lvl->btn.position[1]+0.5f,
+                    1.0f };
+
+            m3x3_mulv( vg.pv, pos, pos );
+            pos[0] += 1.0f;
+            pos[0] *= (f32)vg.window_x * 0.5f;
+            pos[1] += 1.0f;
+            pos[1] = 2.0f - pos[1];
+            pos[1] *= (f32)vg.window_y * 0.5f;
+
+            ui_text( (ui_rect){ pos[0]-100, pos[1], 200, 24 }, num, 1, 
+                     k_ui_align_center, 0xffcccccc );
+         }
+      }
+   }
 
-               music_volume = vg_minf( vg_maxf( offset_local, 0.0f ), 1.0f );
-               music_volume_update();
-            }
-            
-            ui_global_ctx.cursor[0] += 4;
-            ui_global_ctx.cursor[1] += 4;
-            
-            char volbuf[12];
-            snprintf( volbuf, 12, "%.2f", music_volume );
-                               gui_text( ui_global_ctx.cursor, volbuf, 1, 0 );
-                               gui_end_down();
-                       }
-                       gui_end_down();
-               }
-               gui_end();
-       }
-#endif
+   v3f pos = { -2, 8, 1 };
+
+   m3x3_mulv( vg.pv, pos, pos );
+   pos[0] += 1.0f;
+   pos[0] *= (f32)vg.window_x * 0.5f;
+   pos[1] += 1.0f;
+   pos[1] = 2.0f - pos[1];
+   pos[1] *= (f32)vg.window_y * 0.5f;
+
+   char tot[32];
+   snprintf( tot, 31, "%u", sum );
+
+   vg_ui.font = &vg_ui_font_big;
+   ui_text( (ui_rect){ pos[0]-100, pos[1], 200, 24 }, tot, 1, 
+            k_ui_align_center, 0xffcccccc );
+   vg_ui.font = &vg_ui_font_small;
+
+   if( world.pCmpLevel ){
+      vg_ui.font = &vg_ui_font_big;
+      ui_text( (ui_rect){ 0, 0, vg.window_x, 28 }, world.pCmpLevel->title, 
+               1, k_ui_align_middle_center, 0 );
+      vg_ui.font = &vg_ui_font_small;
+      ui_text( (ui_rect){ 0, 28,vg.window_x, 14 }, world.pCmpLevel->description,
+               1, k_ui_align_middle_center, 0 );
+   }
 }
 
 // CONSOLE COMMANDS
@@ -3873,8 +3634,7 @@ void _mc_vg1_ui(void) {
 static int console_credits( int argc, char const *argv[] )
 {
        vg_info( "Aknowledgements:\n" );
-       vg_info( "  GLFW         zlib/libpng  glfw.org\n" );
-       vg_info( "  miniaudio    MIT0         miniaud.io\n" );
+       vg_info( "  SDL2         ZLIB         libsdl.org\n" );
        vg_info( "  QOI          MIT          phoboslab.org\n" );
        vg_info( "  STB library  MIT          nothings.org\n" );
        return 0;
@@ -3995,71 +3755,20 @@ void _mc_vg1_start(void){
        sw_leaderboard_downloaded = &leaderboard_downloaded;
        #endif
 
-#if 0
-       vg_function_push( (struct vg_cmd){
-               .name = "_map_write",
-               .function = console_save_map
-       });
-       
-       vg_function_push( (struct vg_cmd){
-               .name = "_map_load",
-               .function = console_load_map
-       });
-       
-       vg_function_push( (struct vg_cmd){
-               .name = "map",
-               .function = console_changelevel
-       });
-       
-       vg_function_push( (struct vg_cmd){
-               .name = "credits",
-               .function = console_credits
-       });
-
-       vg_convar_push( (struct vg_convar){
-               .name = "colours",
-               .data = &colour_set_id,
-               .data_type = k_convar_dtype_i32,
-               .opt_i32 = { .min = 0, .max = 2, .clamp = 1 },
-               .persistent = 1
-       });
-
-   vg_convar_push( (struct vg_convar){
-      .name = "theme",
-      .data = &world_theme_id,
-      .data_type = k_convar_dtype_i32,
-      .opt_i32 = { .min = 0, .max = vg_list_size( world_themes )-1, .clamp = 1 },
-      .persistent = 1,
-      .update = NULL
-   });
-
-   vg_convar_push( (struct vg_convar){
-      .name = "enable_bloom",
-      .data = &enable_bloom,
-      .data_type = k_convar_dtype_i32,
-      .opt_i32 = { .min = 0, .max = 1, .clamp = 1 },
-      .persistent = 1,
-      .update = NULL
-   });
-
-   vg_convar_push( (struct vg_convar){
-      .name = "enable_vignette",
-      .data = &enable_vignette,
-      .data_type = k_convar_dtype_i32,
-      .opt_i32 = { .min = 0, .max = 1, .clamp = 1 },
-      .persistent = 1,
-      .update = NULL
-   });
-
-   vg_convar_push( (struct vg_convar){
-      .name = "music_volume",
-      .data = &music_volume,
-      .data_type = k_convar_dtype_f32,
-      .opt_f32 = { .min = 0.0f, .max = 1.0f, .clamp = 1 },
-      .persistent = 1,
-      .update = music_volume_update
-   });
-#endif
+   vg_console_reg_cmd( "_map_write", console_save_map, NULL );
+   vg_console_reg_cmd( "_map_load", console_load_map, NULL );
+   vg_console_reg_cmd( "map", console_changelevel, NULL );
+   vg_console_reg_cmd( "credits", console_credits, NULL );
+   vg_console_reg_var( "colours", &marblecomp.colour_set, k_var_dtype_i32,
+                       VG_VAR_PERSISTENT );
+   vg_console_reg_var( "theme", &marblecomp.world_theme, k_var_dtype_i32,
+                       VG_VAR_PERSISTENT );
+   vg_console_reg_var( "enable_bloom", &marblecomp.bloom, k_var_dtype_i32,
+                       VG_VAR_PERSISTENT );
+   vg_console_reg_var( "enable_vignette", &marblecomp.vignette, k_var_dtype_i32,
+                       VG_VAR_PERSISTENT );
+   vg_console_reg_var( "music", &marblecomp.music, k_var_dtype_i32,
+                       VG_VAR_PERSISTENT );
 
        // Combined quad, long quad / empty circle / filled circle mesh
        {
@@ -4226,10 +3935,6 @@ void _mc_vg1_start(void){
 /* FIXME: run this at vg exit */
 void _mc_vg1_free(void)
 {
-#ifdef VG_STEAM
-       sw_free_opengl();
-#endif
-
        console_save_map( 0, NULL );
        career_serialize();
 }
index fe6176c9893a565dc14a86a524b39fb94075804d..35416db7d207a1d1e498541505fd3ebdab2b4f32 100644 (file)
@@ -3,6 +3,7 @@
 #define VG_2D
 #define VG_LOG_SOURCE_INFO
 #define VG_TIMESTEP_FIXED (1.0/60.0)
+#define VG_GAME_SETTINGS
 
 #ifndef VG_RELEASE
  #define VG_DEVWINDOW
@@ -14,7 +15,7 @@
 #include "vg/submodules/stb/stb_ds.h"
 
 #include "vg/vg.h"
-
+#include "steam.h"
 
 struct {
    enum mc_op {
@@ -24,11 +25,15 @@ struct {
    op;
 
    v3f mouse_ws;
+   i32 colour_set, world_theme, bloom, vignette, music;
+   audio_channel *music_channel;
 }
-static marblecomp = { .op = k_mc_op_clientloading };
+static marblecomp = { .op = k_mc_op_clientloading, .bloom = 1, .vignette = 1 };
 
 #include "input.h"
 #include "fishladder_vg1.c"
+#include "marblecomp_settings.h"
+#include "steam.h"
 
 int main( int argc, char *argv[] ){
    vg_mem.use_libc_malloc = 0;
@@ -42,6 +47,7 @@ static void vg_launch_opt(void){
 }
 
 static void vg_preload(void){
+   vg_audio.dsp_enabled = 0;
 vg_info(" Copyright  .        . .       -----, ,----- ,---.   .---.  \n" );
 vg_info(" 2021-2023  |\\      /| |           /  |      |    | |    /| \n" );
 vg_info("            | \\    / | +--        /   +----- +---'  |   / | \n" );
@@ -49,11 +55,23 @@ vg_info("            |  \\  /  | |         /    |      |   \\  |  /  | \n" );
 vg_info("            |   \\/   | |        /     |      |    \\ | /   | \n" );
 vg_info("            '        ' '--' [] '----- '----- '     ' '---'  " 
         "SOFTWARE\n" );
+
+   steam_init();
+   vg_loader_step( NULL, steam_end );
 }
 
 static void async_call_ready( void *payload, u32 size ){
    _mc_vg1_start();
    marblecomp.op = k_mc_op_none;
+
+   audio_lock();
+   if( marblecomp.music ){
+      marblecomp.music_channel = audio_get_first_idle_channel();
+      audio_channel_init( marblecomp.music_channel, &audio_music[0], 
+                          AUDIO_FLAG_LOOP );
+      audio_channel_fadein( marblecomp.music_channel, 0.25f );
+   }
+   audio_unlock();
 }
 
 static void vg_load(void){
@@ -81,6 +99,7 @@ void _mc_vg1_projection_update(void){
 
 
 static void vg_pre_update(void){
+   steam_update();
    if( marblecomp.op == k_mc_op_clientloading ) return;
    skaterift_preupdate_inputs();
    _mc_vg1_update();
diff --git a/marblecomp_settings.h b/marblecomp_settings.h
new file mode 100644 (file)
index 0000000..3952fba
--- /dev/null
@@ -0,0 +1,160 @@
+struct ui_enum_opt mc_settings_colourscheme_enum[] = {
+   { 0, "Normal" },
+   { 1, "Extra1" },
+   { 2, "Extra2" }
+};
+
+struct ui_enum_opt mc_settings_binary[] = {
+   { 1, "Enabled" },
+   { 0, "Disabled" },
+};
+
+struct ui_enum_opt mc_settings_theme_enum[] = {
+   { 0, "Minimal" },
+   { 1, "Wood" },
+   { 2, "Lab" },
+};
+
+struct {
+   struct vg_setting_enum colourscheme, bloom, vignette, theme, music;
+}
+static mc_settings = {
+   .colourscheme = { .label = "Colour Scheme",
+                     .actual_value = &marblecomp.colour_set,
+                     .options = mc_settings_colourscheme_enum, 
+                     .option_count = 3 },
+   .bloom = { .label = "Bloom",
+              .actual_value = &marblecomp.bloom,
+              .options = mc_settings_binary, .option_count = 2 },
+   .vignette = { .label = "Vignette",
+                 .actual_value = &marblecomp.vignette,
+                 .options = mc_settings_binary, .option_count = 2 },
+   .theme = { .label = "Tile Theme",
+               .actual_value = &marblecomp.world_theme,
+               .options = mc_settings_theme_enum, .option_count = 3 },
+   .music = { .label = "Music",
+               .actual_value = &marblecomp.music,
+               .options = mc_settings_binary, .option_count = 2 }
+};
+
+static void vg_game_settings_init(void){
+   ui_settings_enum_init( &mc_settings.colourscheme );
+   ui_settings_enum_init( &mc_settings.bloom );
+   ui_settings_enum_init( &mc_settings.vignette );
+   ui_settings_enum_init( &mc_settings.theme );
+   ui_settings_enum_init( &mc_settings.music );
+}
+
+static void vg_game_settings_gui( ui_rect panel ){
+   ui_rect rq;
+   ui_standard_widget( panel, rq, 1 );
+
+   ui_rect opt, display;
+   ui_split_ratio( rq, k_ui_axis_v, 0.5f, 16, opt, display );
+   vg_settings_enum( &mc_settings.colourscheme, opt );
+
+   ui_rect blocks[4];
+   ui_split_ratio( display, k_ui_axis_v, 0.5f, 2, blocks[0], blocks[2] );
+   ui_split_ratio( blocks[0], k_ui_axis_v, 0.5f, 2, blocks[0], blocks[1] );
+   ui_split_ratio( blocks[2], k_ui_axis_v, 0.5f, 2, blocks[2], blocks[3] );
+
+   v3f *set = colour_sets[ mc_settings.colourscheme.new_value ];
+   for( u32 i=0; i<4; i ++ ){
+      u32 rgb = 0xff000000;
+      for( u32 j=0; j < 3; j ++ )
+         rgb |= (u32)(set[i][j]*255.0f) << j * 8;
+
+      ui_fill( blocks[i], rgb );
+   }
+
+   ui_standard_widget( panel, rq, 1 );
+   vg_settings_enum( &mc_settings.theme, rq );
+
+   ui_standard_widget( panel, rq, 1 );
+   vg_settings_enum( &mc_settings.bloom, rq );
+
+   ui_standard_widget( panel, rq, 1 );
+   vg_settings_enum( &mc_settings.vignette, rq );
+
+   ui_standard_widget( panel, rq, 1 );
+   vg_settings_enum( &mc_settings.music, rq );
+
+   if( vg_settings_apply_button( panel, 1 ) ){
+      marblecomp.colour_set = mc_settings.colourscheme.new_value;
+      marblecomp.world_theme = mc_settings.theme.new_value;
+      marblecomp.bloom = mc_settings.bloom.new_value;
+      marblecomp.vignette = mc_settings.vignette.new_value;
+
+      audio_lock();
+      marblecomp.music = mc_settings.music.new_value;
+
+      if( marblecomp.music ){
+         if( !marblecomp.music_channel ){
+            marblecomp.music_channel = audio_get_first_idle_channel();
+            audio_channel_init( marblecomp.music_channel, &audio_music[0], 
+                                AUDIO_FLAG_LOOP );
+            audio_channel_fadein( marblecomp.music_channel, 0.25f );
+         }
+      }
+      else{
+         if( marblecomp.music_channel ){
+            marblecomp.music_channel = audio_channel_fadeout(
+                  marblecomp.music_channel, 0.25f );
+         }
+      }
+
+      audio_unlock();
+   }
+
+#if 0
+                       ui_global_ctx.cursor[1] += 16;
+                       gui_text( ui_global_ctx.cursor, "Music Volume", 1, 0 );
+                       ui_global_ctx.cursor[1] += 20;
+
+                       gui_new_node();
+                       {
+            ui_px slider_start = ui_global_ctx.cursor[0];
+            
+            float const bar_width = 45.0f,
+                        bar_total = 200.0f,
+                        bar_movement = bar_total-bar_width,
+                        bar_start = bar_width * 0.5f;
+
+                               ui_global_ctx.cursor[2] = bar_total;
+            ui_fill_rect( &ui_global_ctx, 
+                          ui_global_ctx.cursor, 
+                          0xff111111 );
+
+                               ui_global_ctx.cursor[2] = bar_width;
+            ui_global_ctx.cursor[0] = slider_start + music_volume * bar_movement;
+            
+            int status = gui_button( 7 );
+            
+            static ui_px drag_start = 0.0f;
+
+            if( status == k_button_start_click )
+               drag_start = ui_global_ctx.mouse[0];
+            else if( ui_global_ctx.capture_lock && 
+                     (ui_global_ctx.capture_mouse_id == ui_group_id(&ui_global_ctx,7)))
+            {
+               ui_px drag_offset = ui_global_ctx.mouse[0] - drag_start;
+               float offset_local = (drag_start + drag_offset - slider_start - bar_start) / bar_movement;
+
+               music_volume = vg_minf( vg_maxf( offset_local, 0.0f ), 1.0f );
+               music_volume_update();
+            }
+            
+            ui_global_ctx.cursor[0] += 4;
+            ui_global_ctx.cursor[1] += 4;
+            
+            char volbuf[12];
+            snprintf( volbuf, 12, "%.2f", music_volume );
+                               gui_text( ui_global_ctx.cursor, volbuf, 1, 0 );
+                               gui_end_down();
+                       }
+                       gui_end_down();
+               }
+               gui_end();
+       }
+#endif
+}
diff --git a/steam.h b/steam.h
new file mode 100644 (file)
index 0000000..c1a80c3
--- /dev/null
+++ b/steam.h
@@ -0,0 +1,282 @@
+#ifndef STEAM_H
+#define STEAM_H
+
+#define VG_GAME
+#include "vg/vg_steam.h"
+#include "vg/vg_steam_utils.h"
+#include "vg/vg_steam_networking.h"
+#include "vg/vg_steam_auth.h"
+#include "vg/vg_steam_http.h"
+#include "vg/vg_steam_friends.h"
+#include "vg/vg_steam_user_stats.h"
+#include "submodules/anyascii/impl/c/anyascii.c"
+
+/*
+ * We only want to use steamworks if building for the networked version,
+ * theres not much point otherwise. We mainly want steamworks for setting
+ * achievements etc.. so that includes our own server too.
+ *
+ * This file also wraps the functions and interfaces that we want to use to 
+ * make them a bit easier to read, since they are the flat API they have very 
+ * long names. in non-networked builds they will return default errors or do
+ * nothing.
+ */
+
+static char steam_username_at_startup[128] = "Unassigned";
+
+static void recv_steam_warning( int severity, const char *msg )
+{
+   if( severity == 0 )
+      vg_low( "%s\n", msg );
+   else
+      vg_info( "%s\n", msg );
+}
+
+static int steam_ready = 0,
+              steam_stats_ready = 0;
+
+static void *hSteamNetworkingSockets,
+            *hSteamUser;
+
+static ISteamUserStats *hSteamUserStats;
+static HSteamPipe hSteamClientPipe;
+
+static const char *steam_achievement_names[] = 
+{
+   "MASTER_ENGINEER", "CAN_DO_THAT", "BANG", "GOOD_ENOUGH", 
+   "TUTORIALS", "MIGHTY_CONSUMER", "GRADUATE"
+};
+
+static void steam_store_achievements(void)
+{
+   if( steam_ready && steam_stats_ready ){
+      SteamAPI_ISteamUserStats_StoreStats( hSteamUserStats );
+   }
+}
+
+static void steam_set_achievement( const char *name ){
+   if( steam_ready && steam_stats_ready ){
+      if( SteamAPI_ISteamUserStats_SetAchievement( hSteamUserStats, name ) ){
+         vg_success( "Achievement set! '%s'\n", name );
+
+      }
+      else{
+         vg_warn( "Failed to set achievement: %s\n", name );
+      }
+   }
+   else{
+      vg_warn( "Failed to set achievement (steam not ready): %s\n", name );
+   }
+}
+
+static void sw_set_achievement( const char *name ){
+   steam_set_achievement( name );
+   steam_store_achievements();
+}
+
+static void steam_clear_achievement( const char *name )
+{
+   if( steam_ready && steam_stats_ready ){
+      if( SteamAPI_ISteamUserStats_ClearAchievement( hSteamUserStats, name ) ){
+         vg_info( "Achievement cleared: '%s'\n", name );
+      }
+      else{
+         vg_warn( "Failed to clear achievement: %s\n", name );
+      }
+   }
+   else{
+      vg_warn( "Failed to clear achievement (steam not ready): %s\n", name );
+   }
+}
+
+
+static void steam_print_all_achievements(void){
+   vg_info( "Achievements: \n" );
+
+   if( steam_ready && steam_stats_ready ){
+      for( int i=0; i<vg_list_size(steam_achievement_names); i++ ){
+         steamapi_bool set = 0;
+         const char *name = steam_achievement_names[i];
+
+         if( SteamAPI_ISteamUserStats_GetAchievement( 
+                  hSteamUserStats, name, &set ) )
+         {
+            vg_info( "  %s %s\n", (set? "[YES]": "[   ]"), name );
+         }
+         else{
+            vg_warn( "  Error while fetching achievement status '%s'\n", name );
+         }
+      }
+   }
+   else{
+      vg_warn( "  Steam is not initialized, no results\n" );
+   }
+}
+
+static int steam_achievement_ccmd( int argc, char const *argv[] )
+{
+   if( !(steam_ready && steam_stats_ready) ){
+      vg_error( "steam_ready: %d, steam_stats_ready: %d\n",
+                  steam_ready, steam_stats_ready );
+      return 1;
+   }
+
+   if( argc == 1 ){
+      if( !strcmp( argv[0], "list" ) ){
+         steam_print_all_achievements();
+         return 0;
+      }
+      else if( !strcmp( argv[0], "clearall" )){
+         for( int i=0; i<vg_list_size(steam_achievement_names); i++ )
+            steam_clear_achievement( steam_achievement_names[i] );
+         
+         steam_store_achievements();
+      }
+   }
+
+   if( argc == 2 ){
+      if( !strcmp( argv[0], "set" ) ){
+         steam_set_achievement( argv[1] );
+         steam_store_achievements();
+         return 0;
+      }
+      else if( strcmp( argv[0], "clear" ) ){
+         steam_clear_achievement( argv[1] );
+         steam_store_achievements();
+         return 0;
+      }
+   }
+
+   return 1;
+}
+
+static void steam_on_recieve_current_stats( CallbackMsg_t *msg )
+{
+   UserStatsReceived_t *rec = (UserStatsReceived_t *)msg->m_pubParam;
+
+   if( rec->m_eResult == k_EResultOK ){
+      vg_info( "Recieved stats for: %lu (user: %lu)\n", rec->m_nGameID,
+                                                        rec->m_steamIDUser );
+      steam_stats_ready = 1;
+   }
+   else{
+      vg_error( "Error recieveing stats for user (%u)\n", rec->m_eResult );
+   }
+}
+
+static u32 utf8_byte0_byte_count( u8 char0 )
+{
+   for( u32 k=2; k<4; k++ ){
+      if( !(char0 & (0x80 >> k)) )
+         return k;
+   }
+
+   return 0;
+}
+
+static u32 str_utf8_collapse( const char *str, char *buf, u32 length ){
+   u8 *ustr = (u8 *)str;
+   u32 utf32_code = 0x00000000;
+   u32 i=0, j=0, utf32_byte_ct=0;
+
+   for(;j < length-1;){
+      if( ustr[i] == 0x00 )
+         break;
+      
+      if( ustr[i] & 0x80 ){
+         if( utf32_byte_ct ){
+            utf32_byte_ct --;
+            utf32_code |= (ustr[i] & 0x3F) << (utf32_byte_ct*6);
+
+            if( !utf32_byte_ct ){
+               const char *match;
+               size_t chars = anyascii( utf32_code, &match );
+
+               for( u32 k=0; k<VG_MIN(chars, length-1-j); k++ ){
+                  buf[ j++ ] = (u8)match[k];
+               }
+            }
+         }
+         else{
+            utf32_byte_ct = utf8_byte0_byte_count( ustr[i] )-1;
+            utf32_code = ustr[i] & (0x3F >> utf32_byte_ct);
+            utf32_code <<= utf32_byte_ct*6;
+         }
+      }
+      else{
+         utf32_byte_ct = 0x00;
+         buf[j ++] = str[i];
+      }
+
+      i++;
+   }
+
+   buf[j] = 0x00;
+   return j;
+}
+
+static int steam_init(void){
+   const char *username = "offline player";
+
+   vg_info( "Initializing steamworks\n" );
+
+   if( !SteamAPI_Init() ){
+      printf("\n");
+      vg_error( "Steamworks failed to initialize\n" );
+      return 1;
+   }
+
+   steam_ready = 1;
+
+   SteamAPI_ManualDispatch_Init();
+
+   /* Connect interfaces */
+   hSteamClientPipe = SteamAPI_GetHSteamPipe();
+   hSteamNetworkingSockets = SteamAPI_SteamNetworkingSockets_SteamAPI();
+   hSteamUser = SteamAPI_SteamUser();
+
+   ISteamUtils *utils = SteamAPI_SteamUtils();
+   SteamAPI_ISteamUtils_SetWarningMessageHook( utils, recv_steam_warning );
+
+   printf("\n");
+   vg_success( "\nSteamworks API running\n" );
+
+   ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
+   username = SteamAPI_ISteamFriends_GetPersonaName( hSteamFriends );
+
+   /*
+    * Request stats
+    * --------------------------------------------------------
+    */
+   hSteamUserStats = SteamAPI_SteamUserStats();
+   steam_register_callback( k_iUserStatsReceived,
+                            steam_on_recieve_current_stats );
+
+   if( !SteamAPI_ISteamUserStats_RequestCurrentStats( hSteamUserStats ) )
+      vg_warn( "No Steam Logon: Cannot request stats\n" );
+
+   vg_console_reg_cmd( "ach", steam_achievement_ccmd, NULL );
+
+   /* TODO: On username update callback */
+   str_utf8_collapse( username, steam_username_at_startup, 
+                        vg_list_size(steam_username_at_startup) );
+
+   return 1;
+}
+
+static void steam_update(void)
+{
+   if( steam_ready ){
+      steamworks_event_loop( hSteamClientPipe );
+   }
+}
+
+static void steam_end(void)
+{
+   if( steam_ready ){
+      vg_info( "Shutting down\n..." );
+      SteamAPI_Shutdown();
+   }
+}
+
+#endif /* STEAM_H */