- data++;
- }
-
- glGenTextures( 1, &vg_ui.tex_glyphs );
- glBindTexture( GL_TEXTURE_2D, vg_ui.tex_glyphs );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, 256, 256, 0,
- GL_RED, GL_UNSIGNED_BYTE, image );
-
- VG_CHECK_GL_ERR();
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-}
-
-enum ui_shader {
- k_ui_shader_colour,
- k_ui_shader_image
-};
-
-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 )
-{
- 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),
-
- indice_offset = vg_ui.indice_start*sizeof(u16),
- indice_count = vg_ui.cur_indice-vg_ui.indice_start,
- indice_size = indice_count * sizeof(u16);
-
- if( !vertex_size || !indice_size )
- return;
-
- glBindVertexArray( vg_ui.vao );
- glBindBuffer( GL_ARRAY_BUFFER, vg_ui.vbo );
- glBufferSubData( GL_ARRAY_BUFFER, vertex_offset, vertex_size,
- vg_ui.vertex_buffer+vg_ui.vert_start );
-
- glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vg_ui.ebo );
- glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, indice_offset, indice_size,
- vg_ui.indice_buffer+vg_ui.indice_start );
-
- glEnable( GL_BLEND );
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- glBlendEquation( GL_FUNC_ADD );
-
- m3x3f view = M3X3_IDENTITY;
- m3x3_translate( view, (v3f){ -1.0f, 1.0f, 0.0f } );
- m3x3_scale( view, (v3f){ 1.0f/((float)vg.window_x*0.5f),
- -1.0f/((float)vg.window_y*0.5f), 1.0f } );
-
- if( shader == k_ui_shader_colour ){
- glUseProgram( _shader_ui.id );
-
- glUniformMatrix3fv( glGetUniformLocation( _shader_ui.id, "uPv" ), 1,
- GL_FALSE, (float *)view );
-
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, vg_ui.tex_glyphs );
- glUniform1i( glGetUniformLocation( _shader_ui.id, "uTexGlyphs" ), 0 );
- }
- else if( shader == k_ui_shader_image ){
- glUseProgram( _shader_ui_image.id );
- glUniformMatrix3fv( glGetUniformLocation( _shader_ui_image.id, "uPv" ), 1,
- GL_FALSE, (float *)view );
- glUniform1i( glGetUniformLocation(_shader_ui_image.id,"uTexImage"), 0 );
- }
- else
- vg_fatal_error( "Invalid UI shader (%d)\n", shader );
-
- glDrawElements( GL_TRIANGLES, indice_count, GL_UNSIGNED_SHORT,
- (void *)(vg_ui.indice_start*sizeof(u16)) );
-
- glDisable( GL_BLEND );
-
- vg_ui.indice_start = vg_ui.cur_indice;
- vg_ui.vert_start = vg_ui.cur_vert;
-}
-
-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))
- return;
-
- struct ui_vert *vertices = &vg_ui.vertex_buffer[ vg_ui.cur_vert ];
- u16 *indices = &vg_ui.indice_buffer[ vg_ui.cur_indice ];
-
- for( int i=0; i<4; i++ ){
- vertices[i].colour = colour;
- }
-
- vertices[0].co[0] = rect[0];
- vertices[0].co[1] = rect[1];
- vertices[0].uv[0] = uv[0];
- vertices[0].uv[1] = uv[1];
- vertices[1].co[0] = rect[0]+rect[2];
- vertices[1].co[1] = rect[1];
- vertices[1].uv[0] = uv[2];
- vertices[1].uv[1] = uv[1];
- vertices[2].co[0] = rect[0]+rect[2];
- vertices[2].co[1] = rect[1]+rect[3];
- vertices[2].uv[0] = uv[2];
- vertices[2].uv[1] = uv[3];
- vertices[3].co[0] = rect[0];
- vertices[3].co[1] = rect[1]+rect[3];
- vertices[3].uv[0] = uv[0];
- vertices[3].uv[1] = uv[3];
- u16 ind_start = vg_ui.cur_vert;
-
- u16 start = vg_ui.cur_vert;
- u32 mesh[] = { 0,2,1, 0,3,2 };
-
- for( u32 i=0; i<vg_list_size(mesh); i++ ){
- indices[i] = start+mesh[i];
- }
-
- vg_ui.cur_indice += 6;
- vg_ui.cur_vert += 4;
-}
-
-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 )
-{
- /* 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))
- return;
-
- struct ui_vert *vertices = &vg_ui.vertex_buffer[ vg_ui.cur_vert ];
- u16 *indices = &vg_ui.indice_buffer[ vg_ui.cur_indice ];
-
- for( int i=0; i<8; i++ ){
- vertices[i].uv[0] = 4;
- vertices[i].uv[1] = 4;
- vertices[i].colour = colour;
- }
-
- vertices[0].co[0] = rect[0];
- vertices[0].co[1] = rect[1];
- vertices[1].co[0] = rect[0]+rect[2];
- vertices[1].co[1] = rect[1];
- vertices[2].co[0] = rect[0]+rect[2];
- vertices[2].co[1] = rect[1]+rect[3];
- vertices[3].co[0] = rect[0];
- vertices[3].co[1] = rect[1]+rect[3];
- vertices[4].co[0] = vertices[0].co[0]-thickness;
- vertices[4].co[1] = vertices[0].co[1]-thickness;
- vertices[5].co[0] = vertices[1].co[0]+thickness;
- vertices[5].co[1] = vertices[1].co[1]-thickness;
- vertices[6].co[0] = vertices[2].co[0]+thickness;
- vertices[6].co[1] = vertices[2].co[1]+thickness;
- vertices[7].co[0] = vertices[3].co[0]-thickness;
- vertices[7].co[1] = vertices[3].co[1]+thickness;
-
- 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; i<vg_list_size(mesh); i++ ){
- indices[i] = start+mesh[i];
- }
-
- vg_ui.cur_indice += 24;
- vg_ui.cur_vert += 8;
-}
-
-static void ui_split_px( ui_rect rect,
- enum ui_axis other, ui_px width, ui_px pad,
- ui_rect l, ui_rect r )
-{
- enum ui_axis dir = other ^ 0x1;
-
- ui_rect temp;
- rect_copy( rect, temp );
-
- l[ dir ] = temp[ dir ] + pad;
- r[ dir ] = temp[ dir ] + width + (pad/2);
- l[ other ] = temp[ other ] + pad;
- r[ other ] = temp[ other ] + pad;
- l[ 2+dir ] = width - ((3*pad)/2);
- r[ 2+dir ] = temp[ 2+dir ] - width - ((3*pad)/2);
- l[ 2+other ] = temp[ 2+other ] - pad*2;
- r[ 2+other ] = temp[ 2+other ] - pad*2;
-}
-
-static void ui_rect_center( ui_rect parent, ui_rect rect )
-{
- rect[0] = parent[0] + (parent[2]-rect[2])/2;
- rect[1] = parent[1] + (parent[3]-rect[3])/2;
-}
-
-static void ui_fit_item( ui_rect rect, ui_px size[2], ui_rect d )
-{
- i32 rp = (i32)rect[2] * (i32)size[1],
- rc = (i32)size[0] * (i32)rect[3];
-
- enum ui_axis dir, other;
- if( rc > rp ) dir = k_ui_axis_h;
- else dir = k_ui_axis_v;
- other = dir ^ 0x1;
-
- d[2+dir] = rect[2+dir];
- d[2+other] = (rect[2+dir] * size[other]) / size[dir];
-
- ui_rect_center( rect, d );
-}
-
-static void ui_split_ratio( ui_rect rect, enum ui_axis dir, float ratio,
- ui_px pad, ui_rect l, ui_rect r )
-{
- ui_px width = (float)rect[ 2+(dir^0x1) ] * ratio;
- ui_split_px( rect, dir, width, pad, l, r );
-}
-
-static void ui_rect_pad( ui_rect rect, ui_px pad )
-{
- rect[0] += pad;
- rect[1] += pad;
- rect[2] -= pad*2;
- rect[3] -= pad*2;
-}