From: hgn Date: Mon, 11 Sep 2023 06:26:51 +0000 (+0100) Subject: general imgui improvements & tabs X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=commitdiff_plain;h=3013df439a15c3c4b4078ea9724f15d6a1cb3820 general imgui improvements & tabs --- diff --git a/compile_font.sh b/compile_font.sh new file mode 100755 index 0000000..929b865 --- /dev/null +++ b/compile_font.sh @@ -0,0 +1 @@ +./vg/bin/fontcomp vg/src/fonts/vg_font_thin.png vg/vg_pxfont_thin.h diff --git a/src/fonts/vg_font_thin.png b/src/fonts/vg_font_thin.png index 78a2cbc..f03727a 100644 Binary files a/src/fonts/vg_font_thin.png and b/src/fonts/vg_font_thin.png differ diff --git a/src/fonts/vg_font_thin.xcf b/src/fonts/vg_font_thin.xcf index a247fcf..9d991f0 100644 Binary files a/src/fonts/vg_font_thin.xcf and b/src/fonts/vg_font_thin.xcf differ diff --git a/src/fonts/vg_font_thin_v1.png b/src/fonts/vg_font_thin_v1.png new file mode 100644 index 0000000..78a2cbc Binary files /dev/null and b/src/fonts/vg_font_thin_v1.png differ diff --git a/submodules/SDL_GameControllerDB b/submodules/SDL_GameControllerDB index 6ed8d05..c5b4df0 160000 --- a/submodules/SDL_GameControllerDB +++ b/submodules/SDL_GameControllerDB @@ -1 +1 @@ -Subproject commit 6ed8d054340ee8a93a684e11360b66cd8a5c168e +Subproject commit c5b4df0e1061175cb11e3ebbf8045178339864a5 diff --git a/submodules/anyascii b/submodules/anyascii index 44e971c..eb5332d 160000 --- a/submodules/anyascii +++ b/submodules/anyascii @@ -1 +1 @@ -Subproject commit 44e971c774d9ec67ca6c1f16c5a476724821ab63 +Subproject commit eb5332d0b5e48d58397e6f27475a18e058330d23 diff --git a/submodules/qoi b/submodules/qoi index b8d77df..dfc056e 160000 --- a/submodules/qoi +++ b/submodules/qoi @@ -1 +1 @@ -Subproject commit b8d77df1e80b652a57f0b7270449b179a6b91f40 +Subproject commit dfc056e813c98d307238d35f7f041a725d699dfc diff --git a/submodules/stb b/submodules/stb index 8b5f1f3..5736b15 160000 --- a/submodules/stb +++ b/submodules/stb @@ -1 +1 @@ -Subproject commit 8b5f1f37b5b75829fc72d38e7b5d4bcbf8a26d55 +Subproject commit 5736b15f7ea0ffb08dd38af21067c314d6a3aae9 diff --git a/vg_console.h b/vg_console.h index a38a64d..25bad63 100644 --- a/vg_console.h +++ b/vg_console.h @@ -682,7 +682,7 @@ VG_STATIC void _vg_console_draw(void) SDL_AtomicLock( &log_print_sl ); int ptr = vg_log.log_line_current; - int const fh = 14, log_lines = 32; + int const fh = vg_ui.font->line_height, log_lines = 32; int console_lines = VG_MIN( log_lines, vg_log.log_line_count ); ui_rect rect_log = { 0, 0, vg.window_x, log_lines*fh }, @@ -716,7 +716,8 @@ VG_STATIC void _vg_console_draw(void) .change = _vg_console_on_update, .enter = _vg_console_on_enter }; - ui_textbox( rect_input, vg_console.input, vg_list_size(vg_console.input), + ui_textbox( rect_input, NULL, + vg_console.input, vg_list_size(vg_console.input), 1, UI_TEXTBOX_AUTOFOCUS, &callbacks ); /* @@ -726,9 +727,9 @@ VG_STATIC void _vg_console_draw(void) ui_rect rect_suggest; rect_copy( rect_input, rect_suggest ); - rect_suggest[0] += 6 + UI_GLYPH_SPACING_X*vg_console.suggestion_pastepos; + rect_suggest[0] += 6 + vg_ui.font->spacing*vg_console.suggestion_pastepos; rect_suggest[1] += rect_input[3]; - rect_suggest[2] = UI_GLYPH_SPACING_X * vg_console.suggestion_maxlen; + rect_suggest[2] = vg_ui.font->spacing * vg_console.suggestion_maxlen; rect_suggest[3] = vg_console.suggestion_count * fh; ui_fill( rect_suggest, bg_colour ); diff --git a/vg_imgui.h b/vg_imgui.h index 8938acb..6e8537c 100644 --- a/vg_imgui.h +++ b/vg_imgui.h @@ -52,7 +52,7 @@ enum ui_align struct ui_vert { ui_px co[2]; - u8 uv[2]; + u16 uv[2]; u32 colour; }; #pragma pack(pop) @@ -73,11 +73,45 @@ enum ui_scheme_colour{ }; static ui_px k_ui_widget_height = 28, - k_ui_scale = 2, + k_ui_scale = 1, k_ui_padding = 8; typedef u32 ui_scheme[8*4]; +struct ui_font { + ui_px glyph_width, + glyph_height, + glyph_baseline, + line_height, + sheet_size, + spacing, + offset_y; + + u8 ascii_start; +}; +typedef struct ui_font ui_font; + +static const ui_font vg_ui_font_small = { + .glyph_width = 8, + .glyph_height = 14, + .glyph_baseline = 4, + .line_height = 14, + .sheet_size = 256, + .spacing = 8, + .ascii_start = ' ', + .offset_y = 0 +}, +vg_ui_font_big = { + .glyph_width = 12, + .glyph_height = 21, + .glyph_baseline = 6, + .line_height = 21, + .sheet_size = 256, + .spacing = 10, + .ascii_start = ' ', + .offset_y = 84 +}; + #define UI_RGB( STDHEX ) 0xff000000 |\ ((STDHEX&0x000000ff)<<16) |\ ((STDHEX&0x0000ff00) ) |\ @@ -97,6 +131,11 @@ typedef u32 ui_scheme[8*4]; #define UI_MOUSE_RIGHT (SDL_BUTTON(SDL_BUTTON_RIGHT)) #define UI_MOUSE_MIDDLE (SDL_BUTTON(SDL_BUTTON_MIDDLE)) +#define UI_TOP 0x1 +#define UI_LEFT 0x2 +#define UI_BOTTOM 0x4 +#define UI_RIGHT 0x8 + struct{ struct ui_vert *vertex_buffer; u16 *indice_buffer; @@ -170,6 +209,7 @@ struct{ float click_fade_opacity; ui_scheme scheme; + const ui_font *font; enum ui_cursor{ k_ui_cursor_default, @@ -217,7 +257,8 @@ static vg_ui = { [ k_ui_blue + k_ui_brighter ] = UI_RGB( 0x83a598 ), [ k_ui_purple + k_ui_brighter ] = UI_RGB( 0xd3869b ), [ k_ui_gray + k_ui_brighter ] = UI_RGB( 0xa89984 ), - } + }, + .font = &vg_ui_font_small }; static struct vg_shader _shader_ui = @@ -240,7 +281,7 @@ static struct vg_shader _shader_ui = "void main()" "{" "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );" - "aTexCoords = a_uv * 0.0078125;" + "aTexCoords = a_uv * 0.00390625;" /* TODO: Uniform */ "aColour = a_colour;" "aWsp = a_co;" @@ -258,12 +299,6 @@ static struct vg_shader _shader_ui = "" "in vec2 aWsp;" - "vec2 rand_hash22( vec2 p )" - "{" - "vec3 p3 = fract(vec3(p.xyx) * 213.8976123);" - "p3 += dot(p3, p3.yzx+19.19);" - "return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));" - "}" "" "void main()" "{" @@ -279,8 +314,7 @@ static struct vg_shader _shader_ui = } }; -static struct vg_shader _shader_ui_image = -{ +static struct vg_shader _shader_ui_image = { .name = "[vg] ui_image", .link = NULL, .vs = @@ -299,7 +333,7 @@ static struct vg_shader _shader_ui_image = "void main()" "{" "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );" - "aTexCoords = a_uv * 0.0078125;" + "aTexCoords = a_uv * 0.00390625;" "aColour = a_colour;" "aWsp = a_co;" @@ -323,10 +357,8 @@ static struct vg_shader _shader_ui_image = "}" } }; -#define UI_GLYPH_SPACING_X 8 -VG_STATIC void _vg_ui_init(void) -{ +VG_STATIC void _vg_ui_init(void){ if( !vg_shader_compile( &_shader_ui ) || !vg_shader_compile( &_shader_ui_image ) ) vg_fatal_error( "Failed to compile ui shader" ); @@ -367,7 +399,7 @@ VG_STATIC void _vg_ui_init(void) glEnableVertexAttribArray( 0 ); /* UV */ - glVertexAttribPointer( 1, 2, GL_UNSIGNED_BYTE, GL_FALSE, stride, + glVertexAttribPointer( 1, 2, GL_UNSIGNED_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, uv ) ); glEnableVertexAttribArray( 1 ); @@ -408,19 +440,6 @@ VG_STATIC void _vg_ui_init(void) } data++; } - -#if 0 - for( u32 y=1; y<256; y++ ){ - for( u32 x=0; x<256; x++ ){ - u32 above = (y-1)*256 + x, - below = y*256+x; - - if( (image[ below ] == 0) && (image[ above ] == 255) ){ - image[ below ] = 128; - } - } - } -#endif glGenTextures( 1, &vg_ui.tex_glyphs ); glBindTexture( GL_TEXTURE_2D, vg_ui.tex_glyphs ); @@ -451,14 +470,12 @@ enum ui_shader { k_ui_shader_image }; -static void rect_copy( ui_rect a, ui_rect b ) -{ +static void rect_copy( ui_rect a, ui_rect b ){ for( int i=0; i<4; i++ ) b[i] = a[i]; } -VG_STATIC void ui_flush( enum ui_shader shader ) -{ +VG_STATIC void ui_flush( enum ui_shader shader ){ u32 vertex_offset = vg_ui.vert_start*sizeof(ui_vert), vertex_count = vg_ui.cur_vert-vg_ui.vert_start, vertex_size = vertex_count*sizeof(ui_vert), @@ -518,8 +535,7 @@ VG_STATIC void ui_flush( enum ui_shader shader ) vg_ui.vert_start = vg_ui.cur_vert; } -static void ui_fill_rect( ui_rect rect, u32 colour, ui_px uv[4] ) -{ +static void ui_fill_rect( ui_rect rect, u32 colour, ui_px uv[4] ){ /* this if far from ideal but stops us from crashing */ if( (vg_ui.cur_vert + 4 > vg_ui.max_verts) || (vg_ui.cur_indice + 6 > vg_ui.max_indices)) @@ -561,13 +577,11 @@ static void ui_fill_rect( ui_rect rect, u32 colour, ui_px uv[4] ) vg_ui.cur_vert += 4; } -static void ui_fill( ui_rect rect, u32 colour ) -{ +static void ui_fill( ui_rect rect, u32 colour ){ ui_fill_rect( rect, colour, (ui_px[4]){ 4,4,4,4 } ); } -static void ui_outline( ui_rect rect, ui_px thickness, u32 colour ) -{ +static void ui_outline( ui_rect rect, ui_px thickness, u32 colour, u32 mask ){ /* this if far from ideal but stops us from crashing */ if( (vg_ui.cur_vert + 8 > vg_ui.max_verts) || (vg_ui.cur_indice + 24 > vg_ui.max_indices)) @@ -602,18 +616,24 @@ static void ui_outline( ui_rect rect, ui_px thickness, u32 colour ) u16 start = vg_ui.cur_vert; u32 mesh[] = { 0,5,4, 0,1,5, 1,6,5, 1,2,6, 2,7,6, 2,3,7, 3,4,7, 3,0,4 }; - for( u32 i=0; ispacing; } -static ui_px ui_text_string_height( const char *str ) -{ +static ui_px ui_text_string_height( const char *str ){ int height = 1; const char *_c = str; u8 c; @@ -698,8 +712,7 @@ static ui_px ui_text_string_height( const char *str ) } static ui_px ui_text_aligned_x( const char *str, ui_rect rect, ui_px scale, - enum ui_align align ) -{ + enum ui_align align ){ enum ui_align lwr = k_ui_align_lwr & align; if( lwr == k_ui_align_left ){ return rect[0]; @@ -716,13 +729,11 @@ static ui_px ui_text_aligned_x( const char *str, ui_rect rect, ui_px scale, static ui_px ui_min( ui_px a, ui_px b ){ return ab?a:b; } -static ui_px ui_clamp( ui_px a, ui_px min, ui_px max ) -{ +static ui_px ui_clamp( ui_px a, ui_px min, ui_px max ){ return ui_min( max, ui_max( a, min ) ); } -static int ui_clip( ui_rect parent, ui_rect child, ui_rect clipped ) -{ +static int ui_clip( ui_rect parent, ui_rect child, ui_rect clipped ){ ui_px parent_max[2], child_max[2]; parent_max[0] = parent[0]+parent[2]; parent_max[1] = parent[1]+parent[3]; @@ -744,21 +755,18 @@ static int ui_clip( ui_rect parent, ui_rect child, ui_rect clipped ) return 1; } -static int ui_inside_rect( ui_rect rect, ui_px co[2] ) -{ +static int ui_inside_rect( ui_rect rect, ui_px co[2] ){ if( co[0] >= rect[0] && co[1] >= rect[1] && co[0] < rect[0]+rect[2] && - co[1] < rect[1]+rect[3] ) - { + co[1] < rect[1]+rect[3] ){ return 1; } else return 0; } -static int ui_click_down( u32 mask ) -{ +static int ui_click_down( u32 mask ){ if( vg_ui.ignore_input_frames ) return 0; if( (vg_ui.mouse_state[0] & mask) && !(vg_ui.mouse_state[1] & mask) ) @@ -767,14 +775,12 @@ static int ui_click_down( u32 mask ) return 0; } -static int ui_clicking( u32 mask ) -{ +static int ui_clicking( u32 mask ){ if( vg_ui.ignore_input_frames ) return 0; return vg_ui.mouse_state[0] & mask; } -static int ui_click_up( u32 mask ) -{ +static int ui_click_up( u32 mask ){ if( vg_ui.ignore_input_frames ) return 0; if( (vg_ui.mouse_state[1] & mask) && !(vg_ui.mouse_state[0] & mask) ) @@ -783,8 +789,7 @@ static int ui_click_up( u32 mask ) return 0; } -static void ui_prerender(void) -{ +static void ui_prerender(void){ int x, y; vg_ui.mouse_state[1] = vg_ui.mouse_state[0]; vg_ui.mouse_state[0] = SDL_GetMouseState( &x, &y ); @@ -810,14 +815,12 @@ static void ui_prerender(void) } } -static u32 ui_colour( enum ui_scheme_colour id ) -{ +static u32 ui_colour( enum ui_scheme_colour id ){ return vg_ui.scheme[ id ]; } /* get an appropriately contrasting colour given the base */ -static u32 ui_colourcont( enum ui_scheme_colour id ) -{ +static u32 ui_colourcont( enum ui_scheme_colour id ){ if ( id < k_ui_bg+6 ) return ui_colour( k_ui_fg ); else if( id < k_ui_fg ) return ui_colour( k_ui_bg+1 ); else if( id < k_ui_hue ) return ui_colour( k_ui_bg+3 ); @@ -825,8 +828,7 @@ static u32 ui_colourcont( enum ui_scheme_colour id ) else return ui_colour( k_ui_fg+1 ); } -static void ui_hex_to_norm( u32 hex, v4f norm ) -{ +static void ui_hex_to_norm( u32 hex, v4f norm ){ norm[0] = ((hex ) & 0xff); norm[1] = ((hex>>8 ) & 0xff); norm[2] = ((hex>>16) & 0xff); @@ -834,9 +836,22 @@ static void ui_hex_to_norm( u32 hex, v4f norm ) v4_muls( norm, 1.0f/255.0f, norm ); } +static void ui_text_glyph( const struct ui_font *font, ui_px scale, + u8 glyph, ui_rect out_texcoords ){ + glyph -= font->ascii_start; + + ui_px per_row = font->sheet_size / font->glyph_width, + column = (ui_px)glyph % per_row, + row = (glyph - column) / per_row; + + out_texcoords[0] = column * font->glyph_width; + out_texcoords[1] = row * font->glyph_height + font->offset_y; + out_texcoords[2] = out_texcoords[0] + font->glyph_width; + out_texcoords[3] = out_texcoords[1] + font->glyph_height; +} + static u32 ui_ntext( ui_rect rect, const char *str, u32 len, ui_px scale, - enum ui_align align, u32 colour ) -{ + enum ui_align align, u32 colour ){ ui_rect text_cursor; if( colour == 0 ) colour = ui_colour( k_ui_fg ); @@ -847,8 +862,8 @@ static u32 ui_ntext( ui_rect rect, const char *str, u32 len, ui_px scale, text_cursor[0] = ui_text_aligned_x( str, rect, scale, align ); text_cursor[1] = rect[1]; - text_cursor[2] = 8*scale; - text_cursor[3] = 14*scale; + text_cursor[2] = vg_ui.font->glyph_width*scale; + text_cursor[3] = vg_ui.font->glyph_height*scale; u32 printed_chars = 0; @@ -864,52 +879,29 @@ static u32 ui_ntext( ui_rect rect, const char *str, u32 len, ui_px scale, while( (c = *(_c ++)) ){ if( printed_chars >= len ){ printed_chars = 0; - text_cursor[1] += 14*scale; + text_cursor[1] += vg_ui.font->line_height*scale; text_cursor[0] = ui_text_aligned_x( _c, rect, scale, align ); - text_cursor[0] -= UI_GLYPH_SPACING_X*scale; - - u8 glyph_base[2]; - u8 glyph_index = '\xb6'; - glyph_base[0] = glyph_index & 0xf; - glyph_base[1] = (glyph_index-glyph_base[0])>>4; - glyph_base[0] *= 8; - glyph_base[1] *= 8; - - ui_fill_rect( text_cursor, 0x00ffffff, (ui_px[4]) - { - glyph_base[0]+2, - glyph_base[1]+1, - glyph_base[0]+6, - glyph_base[1]+8 - }); - - text_cursor[0] += UI_GLYPH_SPACING_X*scale; + text_cursor[0] -= vg_ui.font->spacing*scale; + + ui_rect glyph; + ui_text_glyph( vg_ui.font, scale, '\xb6' /*FIXME*/, glyph ); + ui_fill_rect( text_cursor, 0x00ffffff, glyph ); + text_cursor[0] += vg_ui.font->spacing*scale; } if( c == '\n' ){ - text_cursor[1] += 14*scale; + text_cursor[1] += vg_ui.font->line_height*scale; text_cursor[0] = ui_text_aligned_x( _c, rect, scale, align ); printed_chars = 0; continue; } else if( c >= 33 ){ - u8 glyph_base[2]; - u8 glyph_index = c; - glyph_base[0] = glyph_index & 0xf; - glyph_base[1] = (glyph_index-glyph_base[0])>>4; - glyph_base[0] *= 8; - glyph_base[1] *= 8; - - ui_rect rect_char; - - if( ui_clip( rect, text_cursor, rect_char ) ){ - ui_fill_rect( rect_char, colour, (ui_px[4]) - { - glyph_base[0]+2, - glyph_base[1]+1, - glyph_base[0]+6, - glyph_base[1]+8 - }); + ui_rect glyph; + ui_text_glyph( vg_ui.font, scale, c, glyph ); + + ui_rect cursor_clipped; + if( ui_clip( rect, text_cursor, cursor_clipped ) ){ + ui_fill_rect( cursor_clipped, colour, glyph ); } } else if( c == '\x1B' ){ @@ -948,12 +940,12 @@ static u32 ui_ntext( ui_rect rect, const char *str, u32 len, ui_px scale, continue; } else if( c == '\t' ){ - text_cursor[0] += UI_GLYPH_SPACING_X*scale*4; + text_cursor[0] += vg_ui.font->spacing*scale*4; printed_chars += 4; continue; } - text_cursor[0] += UI_GLYPH_SPACING_X*scale; + text_cursor[0] += vg_ui.font->spacing*scale; printed_chars ++; } @@ -961,13 +953,39 @@ static u32 ui_ntext( ui_rect rect, const char *str, u32 len, ui_px scale, } static void ui_text( ui_rect rect, const char *str, ui_px scale, - enum ui_align align, u32 colour ) -{ + enum ui_align align, u32 colour ){ ui_ntext( rect, str, 1024, scale, align, colour ); } -static void ui_image( ui_rect rect, GLuint image ) -{ +/* + * Standard layout stuff + * ----------------------------------------------------------------------------- + */ + +static void ui_panel( ui_rect in_rect, ui_rect out_panel ){ + ui_fill( in_rect, ui_colour( k_ui_bg+1 ) ); + ui_outline( in_rect, 1, ui_colour( k_ui_bg+7 ), 0 ); + rect_copy( in_rect, out_panel ); + ui_rect_pad( out_panel, (ui_px[2]){ k_ui_padding, k_ui_padding } ); +} + +static void ui_label( ui_rect rect, const char *text, ui_px size, + ui_px gap, ui_rect r ){ + ui_rect l; + ui_px width = (ui_text_line_width(text)+vg_ui.font->spacing) * size; + ui_split( rect, k_ui_axis_v, width, gap, l, r ); + ui_text( l, text, 1, k_ui_align_middle_left, 0 ); +} + +static void ui_standard_widget( ui_rect inout_panel, ui_rect out_rect, + ui_px count ){ + ui_px height = (count * vg_ui.font->glyph_height + 18) * k_ui_scale; + ui_split( inout_panel, k_ui_axis_h, height, k_ui_padding, + out_rect, inout_panel ); +} + + +static void ui_image( ui_rect rect, GLuint image ){ ui_flush( k_ui_shader_colour ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, image ); @@ -975,8 +993,7 @@ static void ui_image( ui_rect rect, GLuint image ) ui_flush( k_ui_shader_image ); } -static u32 v4f_u32_colour( v4f colour ) -{ +static u32 v4f_u32_colour( v4f colour ){ u32 r = colour[0] * 255.0f, g = colour[1] * 255.0f, b = colour[2] * 255.0f, @@ -985,8 +1002,7 @@ static u32 v4f_u32_colour( v4f colour ) return r | (g<<8) | (b<<16) | (a<<24); } -static void ui_defocus_all(void) -{ +static void ui_defocus_all(void){ if( vg_ui.focused_control_type == k_ui_control_textbox ){ SDL_StopTextInput(); } @@ -1049,7 +1065,7 @@ static enum ui_button_state ui_colourbutton( ui_rect rect, } else{ ui_fill( rect, col_base ); - ui_outline( rect, 1, col_highlight ); + ui_outline( rect, 1, col_highlight, 0 ); return k_ui_button_holding_outside; } } @@ -1090,9 +1106,15 @@ static enum ui_button_state ui_button_text( ui_rect rect, return ui_colourbutton_text( rect, string, scale, k_ui_bg+4 ); } +static enum ui_button_state ui_button( ui_rect inout_panel, + const char *string ){ + ui_rect rect; + ui_standard_widget( inout_panel, rect, 1 ); + return ui_colourbutton_text( rect, string, 1, k_ui_bg+4 ); +} + static void ui_enum_post(void); -static void ui_postrender(void) -{ +static void ui_postrender(void){ if( vg_ui.click_fade_opacity > 0.0f ){ float scale = vg_ui.click_fade_opacity; scale = vg_maxf( 1.0f/255.0f, scale*scale ); @@ -1132,7 +1154,7 @@ static void ui_postrender(void) ui_rect_center( screen, box ); ui_fill( box, ui_colour(k_ui_bg) ); - ui_outline( box, -1, colour ); + ui_outline( box, -1, colour, 0 ); ui_rect message; rect_copy( box, message ); @@ -1141,8 +1163,8 @@ static void ui_postrender(void) ui_rect row0, row1, btn; ui_split_ratio( message, k_ui_axis_h, 0.5f, 0, row0, row1 ); - row0[0] += UI_GLYPH_SPACING_X; - ui_ntext( row0, vg_ui.modal.message, (box[2]/UI_GLYPH_SPACING_X)-2, 1, + row0[0] += vg_ui.font->spacing; + ui_ntext( row0, vg_ui.modal.message, (box[2]/vg_ui.font->spacing)-2, 1, k_ui_align_left, colour ); rect_copy( row1, btn ); @@ -1176,48 +1198,6 @@ static void ui_postrender(void) SDL_ShowCursor(1); } -static void ui_dev_colourview(void) -{ - ui_rect window = {vg.window_x-256,0,256,vg.window_y}, swatch; - - const char *names[vg_list_size(vg_ui.scheme)] = { - [k_ui_bg] = "k_ui_bg", "k_ui_bg+1", "k_ui_bg+2", "k_ui_bg+3", - "k_ui_bg+4", "k_ui_bg+5", "k_ui_bg+6", "k_ui_bg+7", - - [k_ui_fg] = "k_ui_fg", "k_ui_fg+1", "k_ui_fg+2", "k_ui_fg+3", - "k_ui_fg+4", "k_ui_fg+5", "k_ui_fg+6", "k_ui_fg+7", - - [k_ui_red] = "k_ui_red", "k_ui_orange", "k_ui_yellow", "k_ui_green", - "k_ui_aqua", "k_ui_blue", "k_ui_purple", "k_ui_gray", - "k_ui_red+8","k_ui_orange+8","k_ui_yellow+8","k_ui_green+8", - "k_ui_aqua+8","k_ui_blue+8","k_ui_purple+8","k_ui_gray+8" }; - - ui_rect col[2]; - ui_split_ratio( window, k_ui_axis_v, 0.5f, 0, col[0], col[1] ); - - for( int i=0; i 0 ); + assert( buf ); + + if( lines > 1 ) flags |= UI_TEXTBOX_MULTILINE; + + ui_rect rect; + ui_standard_widget( inout_panel, rect, lines ); + + if( label ) + ui_label( rect, label, 1, 0, rect ); + int clickup= ui_click_up(UI_MOUSE_LEFT), clickdown = ui_click_down(UI_MOUSE_LEFT), click = ui_clicking(UI_MOUSE_LEFT) | clickup, @@ -1743,7 +1744,7 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, rect_copy( rect, text_rect ); if( flags & UI_TEXTBOX_MULTILINE ) text_rect[3] = rect[3]-16; - else text_rect[3] = 14; + else text_rect[3] = vg_ui.font->line_height; text_rect[2] -= 16; ui_rect_center( rect, text_rect ); @@ -1751,7 +1752,7 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, ui_px wrap_length = 1024; if( flags & UI_TEXTBOX_WRAP ) - wrap_length = text_rect[2] / UI_GLYPH_SPACING_X; + wrap_length = text_rect[2] / vg_ui.font->spacing; if( hover ){ vg_ui.cursor = k_ui_cursor_ibeam; @@ -1768,13 +1769,13 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, vg_ui.focused_control_hit = 1; if( click && target ){ int p0[3] ={ - (vg_ui.mouse_click[0] - text_rect[0]) / UI_GLYPH_SPACING_X, - (vg_ui.mouse_click[1] - text_rect[1]) / 14, + (vg_ui.mouse_click[0] - text_rect[0]) / vg_ui.font->spacing, + (vg_ui.mouse_click[1] - text_rect[1]) / vg_ui.font->line_height, -1 }, p1[3] = { - (vg_ui.mouse[0] - text_rect[0]) / UI_GLYPH_SPACING_X, - (vg_ui.mouse[1] - text_rect[1]) / 14, + (vg_ui.mouse[0] - text_rect[0]) / vg_ui.font->spacing, + (vg_ui.mouse[1] - text_rect[1]) / vg_ui.font->line_height, -1 }; @@ -1792,7 +1793,7 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, } } - ui_outline( rect, -2, vg_ui.scheme[ k_ui_orange ] ); + ui_outline( rect, -2, vg_ui.scheme[ k_ui_orange ], 0 ); ui_rect cursor; @@ -1802,15 +1803,14 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, end = VG_MAX( c0, c1 ), chars = end-start; - if( flags & (UI_TEXTBOX_MULTILINE|UI_TEXTBOX_WRAP) ){ - + if( flags & (UI_TEXTBOX_WRAP|UI_TEXTBOX_MULTILINE) ){ int pos[3], remaining = chars; pos[2] = start; _ui_textbox_index_calc_coords( pos, wrap_length ); if( start==end ){ - cursor[0] = text_rect[0] + pos[0]*UI_GLYPH_SPACING_X-1; + cursor[0] = text_rect[0] + pos[0]*vg_ui.font->spacing-1; cursor[1] = text_rect[1] + pos[1]*14; cursor[2] = 2; cursor[3] = 13; @@ -1822,9 +1822,9 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, int run = _ui_textbox_run_remaining( pos, wrap_length ); run = VG_MIN( run, remaining ); - cursor[0] = text_rect[0] + pos[0]*UI_GLYPH_SPACING_X-1; + cursor[0] = text_rect[0] + pos[0]*vg_ui.font->spacing-1; cursor[1] = text_rect[1] + pos[1]*14; - cursor[2] = (float)(run)*(float)UI_GLYPH_SPACING_X; + cursor[2] = (float)(run)*(float)vg_ui.font->spacing; cursor[3] = 13; ui_fill( cursor, col_cursor ); @@ -1838,7 +1838,7 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, } } else{ - cursor[0] = text_rect[0] + start*UI_GLYPH_SPACING_X-1; + cursor[0] = text_rect[0] + start*vg_ui.font->spacing-1; cursor[1] = text_rect[1]; cursor[3] = 13; @@ -1846,7 +1846,7 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, cursor[2] = 2; } else{ - cursor[2] = (float)(chars)*(float)UI_GLYPH_SPACING_X; + cursor[2] = (float)(chars)*(float)vg_ui.font->spacing; } if( (vg_ui.click_fade_opacity<=0.0f) && @@ -1896,13 +1896,59 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags, ui_fill( rect, col_base ); if( hover ){ - ui_outline( rect, -1, col_highlight ); + ui_outline( rect, -1, col_highlight, 0 ); } ui_ntext( text_rect, buf, wrap_length, 1, k_ui_align_left, 0 ); return 0; } +/* + * Tabs + * ----------------------------------------------------------------------------- + */ + +static void ui_tabs( ui_rect inout_panel, ui_rect out_content_panel, + const char **titles, u32 count, i32 *page ){ + ui_rect bar; + ui_standard_widget( inout_panel, bar, 1 ); + + i32 cur_page = *page; + + f32 width = (f32)inout_panel[2] / (f32)count; + + ui_px h = (inout_panel[1] + inout_panel[3]) - (bar[1]+bar[3]); + inout_panel[1] = bar[1]+bar[3]; + inout_panel[3] = h; + + ui_fill( inout_panel, ui_colour( k_ui_bg+2 ) ); + ui_outline( inout_panel, 1, ui_colour( k_ui_bg+5 ), 0 ); + + rect_copy( inout_panel, out_content_panel ); + ui_rect_pad( out_content_panel, (ui_px[2]){ k_ui_padding, k_ui_padding } ); + + /* place buttons */ + for( i32 i=0; i