+static void wbutton_draw( v2i pos, v2f tex, v4f colour )
+{
+ glUniform4f( SHADER_UNIFORM( shader_buttons, "uOffset" ),
+ pos[0],
+ pos[1],
+ tex[0],
+ tex[1]
+ );
+ glUniform4fv( SHADER_UNIFORM( shader_buttons, "uColour" ), 1, colour );
+ draw_mesh( 0, 2 );
+}
+
+static void level_selection_buttons(void)
+{
+ v3f tutorial_colour = { 0.204f, 0.345f, 0.553f };
+ v3f locked_colour = { 0.2f, 0.2f, 0.2f };
+
+ struct button_grid
+ {
+ v3f primary_colour;
+ v2i origin;
+ v2i dims;
+ struct cmp_level *levels;
+ int count;
+ }
+ grids[] =
+ {
+ {
+ .primary_colour = { 0.204f, 0.345f, 0.553f },
+ .origin = { -1, 2 },
+ .dims = { 1, 4 },
+ .levels = cmp_levels_tutorials,
+ .count = vg_list_size( cmp_levels_tutorials )
+ },
+ {
+ .primary_colour = { 0.304f, 0.245f, 0.553f },
+ .origin = { -5, 2 },
+ .dims = { 3, 6 },
+ .levels = cmp_levels_basic,
+ .count = vg_list_size( cmp_levels_basic )
+ },
+ {
+ .primary_colour = { 0.553f, 0.345f, 0.204f },
+ .origin = { -4, 0 },
+ .dims = { 4, 1 },
+ .levels = cmp_levels_grad,
+ .count = vg_list_size( cmp_levels_grad )
+ }
+ };
+
+ v2f tex_coord = { 0.0f, 0.0f };
+ v4f final_colour = { 0.0f, 0.0f, 0.0f, 0.2f };
+ v2i button_pos;
+ static struct cmp_level *select_from = NULL;
+ struct cmp_level *switch_level_to = NULL;
+
+ if( vg_get_button_down( "primary" ) )
+ select_from = NULL;
+
+ for( int i = 0; i < vg_list_size( grids ); i ++ )
+ {
+ struct button_grid *grid = &grids[i];
+
+ int j = 0;
+
+ for( int x = 0; x < grid->dims[0]; x ++ )
+ {
+ for( int y = 0; y < grid->dims[1]; y ++ )
+ {
+ if( j < grid->count )
+ {
+ struct cmp_level *lvl = &grid->levels[ j ];
+
+ // Determine colour
+ if( lvl->unlocked )
+ {
+ if( lvl->is_tutorial )
+ v3_copy( tutorial_colour, final_colour );
+ else
+ v3_copy( grid->primary_colour, final_colour );
+
+ if( lvl->completed_score )
+ final_colour[3] = 0.8f;
+ else
+ final_colour[3] = 0.2f;
+ }
+ else v3_copy( locked_colour, final_colour );
+
+ v2i_add( grid->origin, (v2i){ x,y }, button_pos );
+ int is_hovering = v2i_eq( (v2i){world.tile_x, world.tile_y}, button_pos );
+
+ if( is_hovering )
+ {
+ final_colour[3] += 0.1f;
+
+ // Up click
+ if( vg_get_button_up( "primary" ) )
+ if( select_from == lvl && lvl->unlocked )
+ {
+ switch_level_to = lvl;
+ sfx_set_play( &audio_clicks, &audio_system_ui, 1 );
+ }
+
+ // Start click
+ if( vg_get_button_down( "primary" ) )
+ select_from = lvl;
+
+ if( vg_get_button( "primary" ) )
+ final_colour[3] += 0.2f;
+ }
+
+ if( world.pCmpLevel == lvl )
+ final_colour[3] += fabsf(sinf( vg_time * 2.0f )) * 0.2f;
+
+ wbutton_draw( (v2i){ grid->origin[0] + x, grid->origin[1] + y }, tex_coord, final_colour );
+ }
+ else break;
+
+ j ++;
+ }
+ }
+ }
+
+ if( switch_level_to )
+ {
+ if( console_changelevel( 1, &switch_level_to->map_name ) )
+ {
+ world.pCmpLevel = switch_level_to;
+ }
+ }
+}
+