level selector
authorhgn <hgodden00@gmail.com>
Sun, 5 Dec 2021 23:35:27 +0000 (23:35 +0000)
committerhgn <hgodden00@gmail.com>
Sun, 5 Dec 2021 23:35:27 +0000 (23:35 +0000)
fishladder.c
fishladder_resources.h
vg/vg.h
vg/vg_ui.h

index 7cda200bd7727d537cc849e214f27d7c3c3e5ec1..76e09a20dcac919fdadbb0fda5010fd6ce0f758c 100644 (file)
@@ -2240,98 +2240,115 @@ void vg_render(void)
                
        use_mesh( &world.numbers );
        draw_numbers( (v3f){ 2.0f, (float)world.h-1.875f, 0.3333f }, world.score );
                
        use_mesh( &world.numbers );
        draw_numbers( (v3f){ 2.0f, (float)world.h-1.875f, 0.3333f }, world.score );
-               
-       // Level selection UI
-       use_mesh( &world.circle );
-       float ratio = ((float)vg_window_x/(float)vg_window_y);
-       
-       m3x3f ui_view = M3X3_IDENTITY;
-       m3x3_scale( ui_view, (v3f){ 1.0f, ratio, 1.0f } );
-       glUniformMatrix3fv( SHADER_UNIFORM( shader_tile_colour, "uPv" ), 1, GL_FALSE, (float *)ui_view );
+}
 
 
-       // Calculate mouse in UIsp
-       v3f mouse_ui_space = { ((float)vg_mouse[0] / (float)(vg_window_x)) * 2.0f - 1.0f,
-                                                                 (((float)vg_mouse[1] / (float)(vg_window_y)) * 2.0f - 1.0f)*(-1.0f/ratio), 0.0125f };
+static ui_colourset flcol_list_a = {
+       .main = 0xff877979,
+       .hover = 0xffa09393,
+       .active = 0xffbfb1b0
+};
+static ui_colourset flcol_list_b = {
+       .main = 0xff7c6e6e,
+       .hover = 0xffa09393,
+       .active = 0xffbfb1b0
+};
 
 
-       // Get selected level
-       const float selection_scale = 0.05f;
-       int const level_count = vg_list_size( level_pack_1 );
-       int level_select = -1;
-       
-       if( mouse_ui_space[0] <= -0.8f )
-       {
-               float levels_range = (float)level_count*selection_scale*0.6f;
-               float level_offset = ((-mouse_ui_space[1] + levels_range) / levels_range) * 0.5f * (float)level_count;
-               level_select = ceilf( level_offset );
+static ui_colourset flcol_list_complete_a = {
+       .main = 0xff62a064,
+       .hover = 0xff8dc18f,
+       .active = 0xffb2ddb3
+};
 
 
-               // Draw selector
-               if( level_select >= 0 && level_select < vg_list_size( level_pack_1 ) )
-               {
-                       glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.369768f, 0.3654f, 0.42f, 1.0f );
-                       
-                       use_mesh( &world.tile );
-                       glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), 
-                               -1.0f, 
-                               ((float)level_count - (float)level_select * 2.0f ) * selection_scale * 0.6f,
-                               selection_scale
-                       );
-                       draw_mesh( 2, 2 );
-                       
-                       use_mesh( &world.circle );
-                       
-                       if( vg_get_button_down( "primary" ) )
-                       {
-                               console_changelevel( 1, level_pack_1 + level_select );
-                       }
-               }
-       }
-       else mouse_ui_space[1] = INFINITY;
+static ui_colourset flcol_list_complete_b = {
+       .main = 0xff79b37b,
+       .hover = 0xff8dc18f,
+       .active = 0xffb2ddb3
+};
+
+static ui_colourset flcol_list_locked = {
+       .main = 0xff655959,
+       .hover = 0xff655959,
+       .active = 0xff655959
+};
 
 
-       glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.4f, 0.39f, 0.45f, 1.0f );
 
 
-       // Draw levels
-       for( int i = 0; i < level_count; i ++ )
-       {
-               struct career_level *clevel = &career.levels[i];
        
        
-               v3f level_ui_space = { 
-                       -0.97f, 
-                       ((float)level_count - (float)i * 2.0f ) * selection_scale * 0.6f + selection_scale * 0.5f,
-                       selection_scale * 0.5f
-               };
-               
-               float scale = vg_clampf( 1.0f - fabsf(level_ui_space[1] - mouse_ui_space[1]) * 2.0f, 0.9f, 1.0f );
-               level_ui_space[2] *= scale;
+static void draw_levels_list( struct cmp_level *levels, int count, int unlocked )
+{
+       static struct ui_scrollbar sb = {
+               .bar_height = 400
+       };
+       
+       ui_px view_height = ui_global_ctx.cursor[3];
+       ui_px level_height = 50;
+
+       // Level scroll view
+       gui_new_node();
+       {
+               gui_fill_rect( ui_global_ctx.cursor, 0xff5a4e4d );
+               gui_set_clip( ui_global_ctx.cursor );
                
                
-               glUniform3fv( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), 1, level_ui_space );
+               ui_global_ctx.cursor[2] = 14;
+               gui_align_right();
                
                
-               if( clevel->completed )
-                       draw_mesh( filled_start, filled_count );
+               ui_px content_height = count*level_height;
+               if( content_height > view_height )
+               {
+                       ui_scrollbar( &ui_global_ctx, &sb, 1 );
+                       ui_global_ctx.cursor[1] -= ui_calculate_content_scroll( &sb, content_height );
+               }
                else
                else
-                       draw_mesh( empty_start, empty_count );
-       }
-       
-       // Level scores
-       glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.4f*1.25f, 0.39f*1.25f, 0.45f*1.25f, 1.0f );
-       
-       use_mesh( &world.numbers );
-       for( int i = 0; i < level_count; i ++ )
-       {
-               struct career_level *clevel = &career.levels[i];
-       
-               v3f level_ui_space = { 
-                       -0.94f, 
-                       ((float)level_count - (float)i * 2.0f ) * selection_scale * 0.6f + selection_scale * 0.5f,
-                       0.02f
-               };
+               {
+                       gui_fill_rect( ui_global_ctx.cursor, 0xff807373 );
+               }
+               
+               ui_global_ctx.cursor[2] = 240;
+               ui_global_ctx.cursor[3] = level_height;
+               gui_align_left();
+               
+               for( int i = 0; i < count; i ++ )
+               {
+                       struct cmp_level *lvl_info = &levels[i];
                
                
-               if( clevel->completed )
-                       draw_numbers( level_ui_space, clevel->score );
+                       if( i < unlocked )
+                       {
+                               if( lvl_info->completed_score != 0 )
+                                       gui_override_colours( i&0x1? &flcol_list_complete_a: &flcol_list_complete_b );
+                               else
+                                       gui_override_colours( i&0x1? &flcol_list_a: &flcol_list_b );
+                       }
+                       else
+                               gui_override_colours( &flcol_list_locked );
+                       
+                       if( i < unlocked )
+                       {
+                               if( gui_button( 2 + i ) == k_button_click )
+                               {
+                                       console_changelevel( 1, &lvl_info->map_name );
+                               }
+                       
+                               ui_global_ctx.override_colour = 0xffffffff;
+                               gui_text( lvl_info->title, 3, 0 );
+                               ui_global_ctx.cursor[1] += 18;
+                               gui_text( "incomplete", 2, 0 );
+                       }
+                       else
+                       {
+                               gui_button( 2 + i );
+                               
+                               ui_global_ctx.override_colour = 0xff786f6f;
+                               gui_text( "???", 3, 0 );
+                               ui_global_ctx.cursor[1] += 18;
+                               gui_text( "locked", 2, 0 );
+                       }
                        
                        
-               level_ui_space[0] = -0.975f;
-               level_ui_space[1] -= 0.01f;
-               draw_numbers( level_ui_space, i );
+                       gui_end_down();
+               }
+               
+               gui_reset_colours();            
+               gui_release_clip();
        }
        }
+       gui_end_down();
 }
 
 void vg_ui(void)
 }
 
 void vg_ui(void)
@@ -2344,51 +2361,66 @@ void vg_ui(void)
        
        ui_global_ctx.id_base = 4 << 16;
        
        
        ui_global_ctx.id_base = 4 << 16;
        
+       static int pack_selection = 0;
+       static struct pack_info
+       {
+               struct cmp_level *levels;
+               u32 level_count;
+               const char *name;
+       }
+       pack_infos[] = 
+       {
+               {
+                       .levels = cmp_levels_tutorials,
+                       .level_count = vg_list_size(cmp_levels_tutorials),
+                       .name = "Training"
+               },
+               {
+                       .levels = cmp_levels_basic,
+                       .level_count = vg_list_size(cmp_levels_basic),
+                       .name = "Main"
+               },
+               {
+                       .levels = cmp_levels_grad,
+                       .level_count = vg_list_size(cmp_levels_tutorials),
+                       .name = "Expert"
+               }
+       };
+       
        gui_new_node();
        {
                gui_fill_rect( ui_global_ctx.cursor, 0xff5577ff );
                
        gui_new_node();
        {
                gui_fill_rect( ui_global_ctx.cursor, 0xff5577ff );
                
-               gui_text( "MARBLE COMPUTING", 4, 0 );
+               gui_text( "ASSIGNMENTS", 4, 0 );
                
                
-               ui_global_ctx.cursor[1] += 45;
-               ui_global_ctx.cursor[3] = 709;
+               ui_global_ctx.cursor[1] += 30;
+               ui_global_ctx.cursor[3] = 25;
                
                
-               // Level scroll view
                gui_new_node();
                {
                gui_new_node();
                {
-                       gui_fill_rect( ui_global_ctx.cursor, 0xffff7729 );
-                       gui_set_clip( ui_global_ctx.cursor );
-                       
-                       ui_global_ctx.cursor[2] = 16;
-                       gui_align_right();
-                       
-                       static struct ui_scrollbar sb = {
-                               .bar_height = 400
-                       };
-                       ui_scrollbar( &ui_global_ctx, &sb, 0 );
-                       
-                       ui_global_ctx.cursor[2] = 240;
-                       ui_global_ctx.cursor[3] = 50;
-                       gui_align_left();
-                       
-                       ui_px content_height = vg_list_size(cmp_levels_basic)*ui_global_ctx.cursor[3];
-                       ui_global_ctx.cursor[1] -= ui_calculate_content_scroll( &sb, content_height );
+                       ui_rect_pad( ui_global_ctx.cursor, 2 );
+                       ui_global_ctx.cursor[2] = 84;
                        
                        
-                       for( int i = 0; i < vg_list_size(cmp_levels_basic); i ++ )
+                       for( int i = 0; i < 3; i ++ )
                        {
                        {
-                               struct cmp_level *lvl_info = &cmp_levels_basic[i];
-                       
-                               gui_new_node();
-                               {
-                                       gui_fill_rect( ui_global_ctx.cursor, i&0x1?0xff23fce45:0xff8722f8 );
-                                       gui_text( lvl_info->title, 3, 0 );
-                               }
-                               gui_end_down();
-                       }
-                       
-                       gui_release_clip();
+                               if( i == pack_selection )
+                                       gui_override_colours( &flcol_list_locked );
+
+                               if( gui_button( 2000 + i ) == k_button_click )
+                                       pack_selection = i;
+                               
+                               ui_global_ctx.cursor[1] += 2;
+                               gui_text( pack_infos[i].name, 2, 0 );
+                               gui_end_right();
+                               
+                               gui_reset_colours();
+                       } 
                }
                gui_end_down();
                }
                gui_end_down();
+               
+               ui_global_ctx.cursor[3] = 500;
+               
+               draw_levels_list( pack_infos[ pack_selection ].levels, pack_infos[ pack_selection ].level_count, 3 );
        }
        gui_end();
 }
        }
        gui_end();
 }
index da8b8ea2052b31275b22735697b7924168351468..f3b15ca8578b375b164ec58aa18b45a8735c2f74 100644 (file)
@@ -90,12 +90,27 @@ sfx_system audio_system_balls_extra =
        .name = "Balls Extra"
 };
 
        .name = "Balls Extra"
 };
 
+ui_colourset ui_fl_colours = {
+       .main = 0xff807373,
+       .hover = 0xff918484,
+       .active = 0xffad9f9e
+};
+
+ui_colourset ui_fl_colours_inactive = {
+       .main = 0xff655958,
+       .hover = 0xff655958,
+       .active = 0xff655958
+};
+
 static void resource_load_main(void)
 {
        // Textures
        vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
        
        ui_override_font( tex_monofur.name, 7 );
 static void resource_load_main(void)
 {
        // Textures
        vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
        
        ui_override_font( tex_monofur.name, 7 );
+
+       ui_global_ctx.colours_main = &ui_fl_colours;
+       gui_reset_colours();
        
        // Audio
        sfx_set_init( &audio_tile_mod, NULL );
        
        // Audio
        sfx_set_init( &audio_tile_mod, NULL );
@@ -550,6 +565,11 @@ struct cmp_level
        const char *title;
        const char *description;
        
        const char *title;
        const char *description;
        
+       int completed_score;
+       
+       int unlocks;                    // When completed, unlock this many levels
+       int linked_unlocks;     // When unlocked, unlock this many levels additionally
+       
        int serial_id;
 };
 
        int serial_id;
 };
 
@@ -560,28 +580,32 @@ struct cmp_level cmp_levels_tutorials[] =
                .map_name = "cmp_t01",
                .description = "Utilize basic transport methods",
                
                .map_name = "cmp_t01",
                .description = "Utilize basic transport methods",
                
-               .serial_id = 0
+               .serial_id = 0,
+               .unlocks = 1
        },
        {
                .title = "PRINCIPLE 2",
                .map_name = "cmp_t02",
                .description = "Utilize the twisty turny(TM) piece",
                
        },
        {
                .title = "PRINCIPLE 2",
                .map_name = "cmp_t02",
                .description = "Utilize the twisty turny(TM) piece",
                
-               .serial_id = 1
+               .serial_id = 1,
+               .unlocks = 1
        },
        {
                .title = "PRINCIPLE 3",
                .map_name = "cmp_t03",
                .description = "Merge transport into one",
                
        },
        {
                .title = "PRINCIPLE 3",
                .map_name = "cmp_t03",
                .description = "Merge transport into one",
                
-               .serial_id = 2
+               .serial_id = 2,
+               .unlocks = 1,
        },
        {
                .title = "PRINCIPLE 4",
                .map_name = "cmp_t04",
                .description = "Some stages require multiple runs to succeed in order to pass",
                
        },
        {
                .title = "PRINCIPLE 4",
                .map_name = "cmp_t04",
                .description = "Some stages require multiple runs to succeed in order to pass",
                
-               .serial_id = 12
+               .serial_id = 12,
+               .unlocks = 3
        }
 };
 
        }
 };
 
@@ -592,63 +616,72 @@ struct cmp_level cmp_levels_basic[] =
                .map_name = "cmp_b01",
                .description = "Simple maths, branching required.",
                
                .map_name = "cmp_b01",
                .description = "Simple maths, branching required.",
                
-               .serial_id = 3
+               .serial_id = 3,
+               .unlocks = 1
        },
        {
                .title = "SUBDIVISION 2",
                .map_name = "cmp_b02",
                .description = "Simple maths. Futher.",
 
        },
        {
                .title = "SUBDIVISION 2",
                .map_name = "cmp_b02",
                .description = "Simple maths. Futher.",
 
-               .serial_id = 4
+               .serial_id = 4,
+               .unlocks = 1
        },
        {
                .title = "RESTRUCTURE",
                .map_name = "cmp_b03",
                .description = "Not so simple swap",
                
        },
        {
                .title = "RESTRUCTURE",
                .map_name = "cmp_b03",
                .description = "Not so simple swap",
                
-               .serial_id = 5
+               .serial_id = 5,
+               .unlocks = 1
        },
        {
                .title = "SERIALIZE",
                .map_name = "cmp_b04",
                .description = "Merge and sort",
                
        },
        {
                .title = "SERIALIZE",
                .map_name = "cmp_b04",
                .description = "Merge and sort",
                
-               .serial_id = 6
+               .serial_id = 6,
+               .unlocks = 1
        },
        {
                .title = "PATTERNS 1",
                .map_name = "cmp_b05",
                .description = "Replicate",
                
        },
        {
                .title = "PATTERNS 1",
                .map_name = "cmp_b05",
                .description = "Replicate",
                
-               .serial_id = 7
+               .serial_id = 7,
+               .unlocks = 1
        },
        {
                .title = "PATTERNS 2",
                .map_name = "cmp_b06",
                .description = "Replicate MORE",
                
        },
        {
                .title = "PATTERNS 2",
                .map_name = "cmp_b06",
                .description = "Replicate MORE",
                
-               .serial_id = 8
+               .serial_id = 8,
+               .unlocks = 1
        },
        {
                .title = "MIGHTY CONSUMER",
                .map_name = "cmp_b07",
                .description = "Build a greedy system",
                
        },
        {
                .title = "MIGHTY CONSUMER",
                .map_name = "cmp_b07",
                .description = "Build a greedy system",
                
-               .serial_id = 9
+               .serial_id = 9,
+               .unlocks = 1
        },
        {
                .title = "ENCRYPTED 1",
                .map_name = "cmp_b08",
                .description = "Some configurations may not be valid",
 
        },
        {
                .title = "ENCRYPTED 1",
                .map_name = "cmp_b08",
                .description = "Some configurations may not be valid",
 
-               .serial_id = 10
+               .serial_id = 10,
+               .unlocks = 1
        },
        {
                .title = "REVERSE",
                .map_name = "cmp_b09",
                .description = "Reverse the incoming order. Always length 4",
                
        },
        {
                .title = "REVERSE",
                .map_name = "cmp_b09",
                .description = "Reverse the incoming order. Always length 4",
                
-               .serial_id = 11
+               .serial_id = 11,
+               .unlocks = 1
        },
        {
                .title = "PRINCIPLE 5",
        },
        {
                .title = "PRINCIPLE 5",
@@ -661,7 +694,8 @@ struct cmp_level cmp_levels_basic[] =
                        "as part of your training package, you will now be\n"
                        "tasked to complete them",
 
                        "as part of your training package, you will now be\n"
                        "tasked to complete them",
 
-               .serial_id = 15
+               .serial_id = 15,
+               .linked_unlocks = 1
        },
        {
                .title = "ROUTING PROBLEM",
        },
        {
                .title = "ROUTING PROBLEM",
@@ -671,7 +705,8 @@ struct cmp_level cmp_levels_basic[] =
                        "Do your best to utilize principle 5 to get the job\n"
                        "done.",
                
                        "Do your best to utilize principle 5 to get the job\n"
                        "done.",
                
-               .serial_id = 16
+               .serial_id = 16,
+               .unlocks = 1
        },
        {
                .title = "PRINCIPLE 6",
        },
        {
                .title = "PRINCIPLE 6",
@@ -695,7 +730,8 @@ struct cmp_level cmp_levels_basic[] =
                        "time, this results in no operation being performed,\n"
                        "and no state changes take place in the Twisty Turny(TM)\n",
 
                        "time, this results in no operation being performed,\n"
                        "and no state changes take place in the Twisty Turny(TM)\n",
 
-                       .serial_id = 17
+                       .serial_id = 17,
+                       .linked_unlocks = 1
        },
        {
                .title = "NOT GATE",
        },
        {
                .title = "NOT GATE",
@@ -704,7 +740,8 @@ struct cmp_level cmp_levels_basic[] =
                        "Test your knowledge of triggers, build an 'NOT GATE'\n"
                        "emulated by marble logic.",
                
                        "Test your knowledge of triggers, build an 'NOT GATE'\n"
                        "emulated by marble logic.",
                
-               .serial_id = 18
+               .serial_id = 18,
+               .unlocks = 1
        },
        {
                .title = "AND GATE",
        },
        {
                .title = "AND GATE",
@@ -713,7 +750,8 @@ struct cmp_level cmp_levels_basic[] =
                        "A slightly more complicated gate, but shouldn't be\n"
                        "too difficult for your skillset.",
                
                        "A slightly more complicated gate, but shouldn't be\n"
                        "too difficult for your skillset.",
                
-               .serial_id = 19
+               .serial_id = 19,
+               .unlocks = 1
        },
        {
                .title = "QUALIFICATION PROJECT",
        },
        {
                .title = "QUALIFICATION PROJECT",
@@ -721,7 +759,8 @@ struct cmp_level cmp_levels_basic[] =
                .description =
                        "There's no instructions here, resolve and complete this\n"
                        "task to qualify yourself as an official marble engineer",
                .description =
                        "There's no instructions here, resolve and complete this\n"
                        "task to qualify yourself as an official marble engineer",
-               .serial_id = 20
+               .serial_id = 20,
+               .unlocks = 3
        }
 };
 
        }
 };
 
@@ -741,7 +780,7 @@ struct cmp_level cmp_levels_grad[] =
                .title = "THIRDS",
                .map_name = "cmp_i02",
                .description = 
                .title = "THIRDS",
                .map_name = "cmp_i02",
                .description = 
-                       "Spit your inputs up into a third of its value\n"
+                       "Split the inputs up into a third of their values\n"
                        "Is this possible? -HG",
                
                .serial_id = 14
                        "Is this possible? -HG",
                
                .serial_id = 14
@@ -764,3 +803,12 @@ struct cmp_level cmp_levels_grad[] =
                .serial_id = 22
        }
 };
                .serial_id = 22
        }
 };
+
+struct
+{
+       int total_unlocked;
+}
+career_local = 
+{
+       .total_unlocked = 1
+};
diff --git a/vg/vg.h b/vg/vg.h
index cdcf431555158d07289fcd75577550e3a7b2c504..ba392bb99adba028461ce7278a6775880a1c9632 100644 (file)
--- a/vg/vg.h
+++ b/vg/vg.h
@@ -35,8 +35,8 @@ m3x3f vg_pv;
 
 // Engine globals
 GLFWwindow* vg_window;
 
 // Engine globals
 GLFWwindow* vg_window;
-int vg_window_x = 1280;
-int vg_window_y = 720;
+int vg_window_x = 1366;
+int vg_window_y = 768;
 
 v2f vg_mouse;
 v3f vg_mouse_ws;
 
 v2f vg_mouse;
 v3f vg_mouse_ws;
@@ -150,6 +150,7 @@ static void vg_init( int argc, char *argv[], const char *window_name )
        glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
        glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
        glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE );
        glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
        glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
        glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE );
+       glfwWindowHint( GLFW_RESIZABLE, GLFW_FALSE );
        
        glfwWindowHint( GLFW_SAMPLES, 4 );
        
        
        glfwWindowHint( GLFW_SAMPLES, 4 );
        
index 35a3e3b8df9294a8ab30aac94f4d2d41a33bbb72..fe46da0040a8bcd795f9628134d3519d78807b63 100644 (file)
@@ -55,6 +55,26 @@ typedef i16                          ui_px;
 typedef u32                            ui_colour;
 typedef ui_px                          ui_rect[4];
 typedef struct ui_ctx  ui_ctx;
 typedef u32                            ui_colour;
 typedef ui_px                          ui_rect[4];
 typedef struct ui_ctx  ui_ctx;
+typedef struct ui_colourset ui_colourset;
+
+struct ui_colourset
+{
+       union
+       {
+               struct
+               {
+                       ui_colour main;
+                       ui_colour hover;
+                       ui_colour active;
+               };
+               struct
+               {
+                       ui_colour background;
+                       ui_colour bar;
+                       ui_colour bar_hover;
+               };
+       };
+};
 
 struct ui_ctx
 {
 
 struct ui_ctx
 {
@@ -96,6 +116,9 @@ struct ui_ctx
        // User input
        ui_px mouse[2];
        int click_state;        // 0: released, 1: on down, 2: pressed, 3: on release
        // User input
        ui_px mouse[2];
        int click_state;        // 0: released, 1: on down, 2: pressed, 3: on release
+       
+       ui_colourset *colours_main;
+       ui_colourset *colours_current;
 };
 
 // Shortnames
 };
 
 // Shortnames
@@ -105,7 +128,7 @@ struct ui_ctx
 #define gui_hasmouse(...) ui_hasmouse( &ui_global_ctx, __VA_ARGS__)
 #define gui_end() ui_end( &ui_global_ctx )
 #define gui_end_down() ui_end_down( &ui_global_ctx )
 #define gui_hasmouse(...) ui_hasmouse( &ui_global_ctx, __VA_ARGS__)
 #define gui_end() ui_end( &ui_global_ctx )
 #define gui_end_down() ui_end_down( &ui_global_ctx )
-#define gui_end_right() ui_fill_right( &ui_global_ctx )
+#define gui_end_right() ui_end_right( &ui_global_ctx )
 #define gui_fill_y() ui_fill_y( &ui_global_ctx)
 #define gui_fill_x() ui_fill_x( &ui_global_ctx)
 #define gui_align_bottom() ui_align_bottom( &ui_global_ctx )
 #define gui_fill_y() ui_fill_y( &ui_global_ctx)
 #define gui_fill_x() ui_fill_x( &ui_global_ctx)
 #define gui_align_bottom() ui_align_bottom( &ui_global_ctx )
@@ -127,6 +150,10 @@ struct ui_ctx
 #define gui_window(...) ui_window( &ui_global_ctx, __VA_ARGS__)
 #define gui_want_mouse() ui_want_mouse( &ui_global_ctx )
 
 #define gui_window(...) ui_window( &ui_global_ctx, __VA_ARGS__)
 #define gui_want_mouse() ui_want_mouse( &ui_global_ctx )
 
+#define gui_scrollbar(...) ui_scrollbar( &ui_global_ctx, __VA_ARGS__)
+#define gui_override_colours(...) ui_override_colours( &ui_global_ctx, __VA_ARGS__)
+#define gui_reset_colours(...) ui_reset_colours( &ui_global_ctx )
+
 // Globals
 // ===========================================================================================================
 
 // Globals
 // ===========================================================================================================
 
@@ -141,7 +168,16 @@ GLuint ui_ebo;
 #define UI_BUFFER_SIZE 30000
 #define UI_INDEX_SIZE 20000
 
 #define UI_BUFFER_SIZE 30000
 #define UI_INDEX_SIZE 20000
 
-ui_ctx ui_global_ctx = { .padding = 8 };
+ui_colourset ui_default_colours = {
+       .main = 0xff00ff00,
+       .hover = 0xffff00ff,
+       .active = 0xffff0000
+};
+ui_ctx ui_global_ctx = { 
+       .padding = 8, 
+       .colours_current = &ui_default_colours, 
+       .colours_main = &ui_default_colours 
+};
 
 
 // Initialization
 
 
 // Initialization
@@ -678,7 +714,7 @@ static int ui_button( ui_ctx *ctx, u32 id )
                
                if( ui_hasmouse(ctx) )
                {
                
                if( ui_hasmouse(ctx) )
                {
-                       ui_fill_rect( ctx, ctx->cursor, 0xffcccccc );
+                       ui_fill_rect( ctx, ctx->cursor, ctx->colours_current->hover );
                        
                        if( ctx->click_state == 1 )
                        {
                        
                        if( ctx->click_state == 1 )
                        {
@@ -691,7 +727,7 @@ static int ui_button( ui_ctx *ctx, u32 id )
                                return k_button_hold;
                }
                else
                                return k_button_hold;
                }
                else
-                       ui_fill_rect( ctx, ctx->cursor, 0xff999999 );
+                       ui_fill_rect( ctx, ctx->cursor, ctx->colours_current->main );
        }
        
        return k_button_released;
        }
        
        return k_button_released;
@@ -796,8 +832,8 @@ static void ui_scrollbar( ui_ctx *ctx, struct ui_scrollbar *scrollbar, u32 id )
        
        ui_new_node( ctx );
        {
        
        ui_new_node( ctx );
        {
-               ui_fill_rect( ctx, ctx->cursor, 0xff000000 );
-               ui_capture_mouse( ctx, __COUNTER__ );
+               ui_fill_rect( ctx, ctx->cursor, ctx->colours_current->background );
+               ui_capture_mouse( ctx, id );
                
                ctx->cursor[1] += scrollbar->py;
                ctx->cursor[3] = scrollbar->bar_height;
                
                ctx->cursor[1] += scrollbar->py;
                ctx->cursor[3] = scrollbar->bar_height;
@@ -805,14 +841,14 @@ static void ui_scrollbar( ui_ctx *ctx, struct ui_scrollbar *scrollbar, u32 id )
                ui_new_node( ctx );
                {
                        ui_capture_mouse( ctx, __COUNTER__ );
                ui_new_node( ctx );
                {
                        ui_capture_mouse( ctx, __COUNTER__ );
-                       struct ui_vert *drag_bar = ui_fill_rect( ctx, ctx->cursor, 0xff555555 );
+                       struct ui_vert *drag_bar = ui_fill_rect( ctx, ctx->cursor, ctx->colours_current->bar );
 
                        if( ui_hasmouse( ctx ) || scrollbar->drag )
                        {
 
                        if( ui_hasmouse( ctx ) || scrollbar->drag )
                        {
-                               drag_bar[0].colour = 0xff777777;
-                               drag_bar[1].colour = 0xff777777;
-                               drag_bar[2].colour = 0xff777777;
-                               drag_bar[3].colour = 0xff777777;
+                               drag_bar[0].colour = ctx->colours_current->bar_hover;
+                               drag_bar[1].colour = ctx->colours_current->bar_hover;
+                               drag_bar[2].colour = ctx->colours_current->bar_hover;
+                               drag_bar[3].colour = ctx->colours_current->bar_hover;
                        
                                // start drag
                                if( ctx->click_state == 1 )
                        
                                // start drag
                                if( ctx->click_state == 1 )
@@ -834,3 +870,14 @@ static ui_px ui_calculate_content_scroll( struct ui_scrollbar *scrollbar, ui_px
        float range = scrollbar->view_height - scrollbar->bar_height;
        return ((float)scrollbar->py / range) * overlap;
 }
        float range = scrollbar->view_height - scrollbar->bar_height;
        return ((float)scrollbar->py / range) * overlap;
 }
+
+static void ui_override_colours( ui_ctx *ctx, ui_colourset *set )
+{
+       ctx->colours_current = set;
+}
+
+static void ui_reset_colours( ui_ctx *ctx )
+{
+       ctx->colours_current = ctx->colours_main;
+       ctx->override_colour = 0xffffffff;
+}