From: hgn Date: Sun, 30 Apr 2023 18:22:02 +0000 (+0100) Subject: imgui stuff X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=commitdiff_plain;h=4eaab4b787d2534b4dce8114a360183355062d20 imgui stuff --- diff --git a/submodules/SDL b/submodules/SDL index eef4d3c..06492c5 160000 --- a/submodules/SDL +++ b/submodules/SDL @@ -1 +1 @@ -Subproject commit eef4d3c86a653f91b7221c80809ba8ab56f94cf1 +Subproject commit 06492c598158cf825a18aececaf7511d7fd04f48 diff --git a/vg.h b/vg.h index ecb7550..a89d750 100644 --- a/vg.h +++ b/vg.h @@ -253,6 +253,7 @@ VG_STATIC void vg_checkgl( const char *src_info ); #include "vg_tex.h" #include "vg_input.h" #include "vg_ui.h" +#include "vg_imgui.h" #include "vg_lines.h" #include "vg_loader.h" #include "vg_opt.h" @@ -426,6 +427,10 @@ VG_STATIC void _vg_gameloop_render(void) /* ui */ vg.engine_stage = k_engine_stage_ui; { + ui_prerender(); + vg_ui(); + ui_postrender(); +#if 0 ui_begin( vg.window_x, vg.window_y ); /* TODO */ @@ -477,6 +482,7 @@ VG_STATIC void _vg_gameloop_render(void) ui_resolve(); ui_draw( NULL ); +#endif } vg_profile_end( &vg_prof_render ); @@ -724,7 +730,7 @@ VG_STATIC void _vg_init_window( const char *window_name ) #ifdef VG_DEVWINDOW 0, 0, vg.window_x, vg.window_y, - SDL_WINDOW_BORDERLESS|SDL_WINDOW_OPENGL|SDL_WINDOW_INPUT_GRABBED + SDL_WINDOW_BORDERLESS|SDL_WINDOW_OPENGL ))){} #else 0, 0, @@ -829,7 +835,10 @@ VG_STATIC void vg_enter( int argc, char *argv[], const char *window_name ) vg_async_init(); +#ifndef VG_DEVWINDOW SDL_SetRelativeMouseMode(1); +#endif + vg.thread_id_main = SDL_GetThreadID(NULL); /* Opengl-required systems */ diff --git a/vg_audio.h b/vg_audio.h index 0e76efd..120622c 100644 --- a/vg_audio.h +++ b/vg_audio.h @@ -1262,6 +1262,7 @@ VG_STATIC void audio_debug_ui( m4x4f mtx_pv ) * ----------------------------------------------------------------------- */ +#if 0 float budget = ((double)vg_audio.samples_last / 44100.0) * 1000.0; vg_profile_drawn( (struct vg_profile *[]){ &vg_prof_audio_decode, &vg_prof_audio_mix, @@ -1404,6 +1405,7 @@ VG_STATIC void audio_debug_ui( m4x4f mtx_pv ) } } } +#endif audio_unlock(); } diff --git a/vg_console.h b/vg_console.h index d5da847..8d47210 100644 --- a/vg_console.h +++ b/vg_console.h @@ -139,6 +139,7 @@ void vg_console_reg_cmd( const char *alias, VG_STATIC void _vg_console_draw(void) { +#if 0 if( !vg_console.enabled ) return; @@ -223,6 +224,7 @@ VG_STATIC void _vg_console_draw(void) } SDL_AtomicUnlock( &log_print_sl ); +#endif } VG_STATIC int _vg_console_list( int argc, char const *argv[] ) diff --git a/vg_imgui.h b/vg_imgui.h new file mode 100644 index 0000000..d843cdc --- /dev/null +++ b/vg_imgui.h @@ -0,0 +1,832 @@ +/* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved */ + +/* + * Principles: + * + * 1. layout is defined by subdividing + * 2. a parent node should never be resized by the content after creation + * 3. when the ui is in an interactive state, no controls should ever move + */ + + +#ifndef VG_IMGUI_H +#define VG_IMGUI_H + +#define VG_GAME +#include "vg/vg.h" +#include "vg/vg_tex.h" +#include "vg/vg_shader.h" + +typedef i16 ui_px; +typedef u32 ui_colour; +typedef ui_px ui_rect[4]; +typedef struct ui_vert ui_vert; + +enum ui_axis { + k_ui_axis_h = 0x0u, + k_ui_axis_v = 0x1u, +}; + +/* Relative to cursor p0 */ +enum ui_align +{ /* DC BA */ + k_ui_align_left = 0x0000| 0x00, + k_ui_align_right = 0x0000| 0x01, + k_ui_align_center = 0x0000| 0x02, + + k_ui_align_middle = 0x0100, + k_ui_align_middle_left = 0x0100| 0x00, + k_ui_align_middle_right = 0x0100| 0x01, + k_ui_align_middle_center = 0x0100| 0x02, + + k_ui_align_bottom = 0x0200, + k_ui_align_bottom_left = 0x0200| 0x00, + k_ui_align_bottom_right = 0x0200| 0x01, + k_ui_align_bottom_center = 0x0200| 0x02, +}; + +#pragma pack(push,1) +struct ui_vert +{ + ui_px co[2]; + u8 uv[2]; + u32 colour; +}; +#pragma pack(pop) + +struct +{ + struct ui_vert *vertex_buffer; + u16 *indice_buffer; + u32 max_verts, max_indices, + cur_vert, cur_indice, + vert_start, indice_start; + + GLuint tex_glyphs, vao, vbo, ebo; + + ui_px mouse[2], mouse_click[2]; + u32 mouse_state[2]; + u32 ignore_input_frames; + + ui_rect click_fader; + float click_fade_opacity; +} + +static vg_uictx; +static struct vg_shader _shader_ui = +{ + .name = "[vg] ui", + .link = NULL, + .vs = + { + .orig_file = NULL, + .static_src = + "layout (location=0) in vec2 a_co;" + "layout (location=1) in vec2 a_uv;" + "layout (location=2) in vec4 a_colour;" + "uniform mat3 uPv;" + "" + "out vec2 aTexCoords;" + "out vec4 aColour;" + "out vec2 aWsp;" + "" + "void main()" + "{" + "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );" + "aTexCoords = a_uv * 0.0078125;" + "aColour = a_colour;" + + "aWsp = a_co;" + "}", + }, + .fs = + { + .orig_file = NULL, + .static_src = + "uniform sampler2D uTexGlyphs;" + "out vec4 FragColor;" + "" + "in vec2 aTexCoords;" + "in vec4 aColour;" + "" + "in vec2 aWsp;" + "" + "void main()" + "{" + + "vec4 glyph = vec4(1.0,1.0,1.0,1.0);" + + "if( aColour.a == 0.0 )" + "{" + "glyph = texture( uTexGlyphs, aTexCoords );" + "glyph.a = smoothstep( 0.47, 0.53, glyph.r );" + "}" + "else" + "{" + "glyph.a = aColour.a;" + "}" + + "FragColor = vec4( aColour.rgb, glyph.a );" + "}" + } +}; + +static struct vg_shader _shader_ui_image = +{ + .name = "[vg] ui_image", + .link = NULL, + .vs = + { + .orig_file = NULL, + .static_src = + "layout (location=0) in vec2 a_co;" + "layout (location=1) in vec2 a_uv;" + "layout (location=2) in vec4 a_colour;" + "uniform mat3 uPv;" + + "out vec2 aTexCoords;" + "out vec4 aColour;" + "out vec2 aWsp;" + + "void main()" + "{" + "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );" + "aTexCoords = a_uv * 0.0078125;" + "aColour = a_colour;" + + "aWsp = a_co;" + "}", + }, + .fs = + { + .orig_file = NULL, + .static_src = + "uniform sampler2D uTexImage;" + "out vec4 FragColor;" + + "in vec2 aTexCoords;" + "in vec4 aColour;" + "in vec2 aWsp;" + + "void main()" + "{" + "vec4 colour = texture( uTexImage, aTexCoords );" + + /* wtf is this?? */ +#if 0 + "float value = dot(vec4(1.0),colour)*0.25;" + + "vec3 col = vec3(pow(cos(value*3.14159265*2.0)*0.5+0.5,0.5))" + "* vec3(step(value,0.5),0.3,step(1.0-value,0.5));" + "FragColor = vec4( col*4.0, 1.0 );" +#endif + + "FragColor = colour;" + "}" + } +}; +#define UI_GLYPH_SPACING_X 8 + +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" ); + + /* + * Vertex buffer + * ---------------------------------------- + */ + + vg_uictx.max_indices = 20000; + vg_uictx.max_verts = 30000; + + /* Generate the buffer we are gonna be drawing to */ + glGenVertexArrays( 1, &vg_uictx.vao ); + glGenBuffers( 1, &vg_uictx.vbo ); + glGenBuffers( 1, &vg_uictx.ebo ); + + glBindVertexArray( vg_uictx.vao ); + glBindBuffer( GL_ARRAY_BUFFER, vg_uictx.vbo ); + + glBufferData( GL_ARRAY_BUFFER, + vg_uictx.max_verts * sizeof( struct ui_vert ), + NULL, GL_DYNAMIC_DRAW ); + glBindVertexArray( vg_uictx.vao ); + + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vg_uictx.ebo ); + glBufferData( GL_ELEMENT_ARRAY_BUFFER, + vg_uictx.max_indices * sizeof( u16 ), NULL, GL_DYNAMIC_DRAW ); + + VG_CHECK_GL_ERR(); + + /* Set pointers */ + u32 const stride = sizeof( struct ui_vert ); + + /* XY */ + glVertexAttribPointer( 0, 2, GL_SHORT, GL_FALSE, stride, + (void *)offsetof( struct ui_vert, co ) ); + glEnableVertexAttribArray( 0 ); + + /* UV */ + glVertexAttribPointer( 1, 2, GL_UNSIGNED_BYTE, GL_FALSE, stride, + (void *)offsetof( struct ui_vert, uv ) ); + glEnableVertexAttribArray( 1 ); + + /* COLOUR */ + glVertexAttribPointer( 2, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, + (void *)offsetof( struct ui_vert, colour ) ); + glEnableVertexAttribArray( 2 ); + + VG_CHECK_GL_ERR(); + + /* Alloc RAM default context */ + u32 vert_size = vg_uictx.max_verts*sizeof(struct ui_vert), + inds_size = vg_align8( vg_uictx.max_indices*sizeof(u16) ); + + vg_uictx.vertex_buffer = vg_linear_alloc( vg_mem.rtmemory, vert_size ); + vg_uictx.indice_buffer = vg_linear_alloc( vg_mem.rtmemory, inds_size ); + + /* font + * ----------------------------------------------------- + */ + + /* Load default font */ + u32 compressed[] = { + #include "vg/vg_pxfont_thin.h" + }; + + u32 pixels = 0, total = 256*256, data = 0; + u8 image[256*256]; + + while( pixels < total ){ + for( int b = 31; b >= 0; b-- ){ + image[ pixels ++ ] = (compressed[data] & (0x1u << b))? 0xffu: 0x00u; + + if( pixels >= total ){ + total = 0; + break; + } + } + data++; + } + + glGenTextures( 1, &vg_uictx.tex_glyphs ); + glBindTexture( GL_TEXTURE_2D, vg_uictx.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_uictx.vert_start*sizeof(ui_vert), + vertex_count = vg_uictx.cur_vert-vg_uictx.vert_start, + vertex_size = vertex_count*sizeof(ui_vert), + + indice_offset = vg_uictx.indice_start*sizeof(u16), + indice_count = vg_uictx.cur_indice-vg_uictx.indice_start, + indice_size = indice_count * sizeof(u16); + + if( !vertex_size || !indice_size ) + return; + + glBindVertexArray( vg_uictx.vao ); + glBindBuffer( GL_ARRAY_BUFFER, vg_uictx.vbo ); + glBufferSubData( GL_ARRAY_BUFFER, vertex_offset, vertex_size, + vg_uictx.vertex_buffer+vg_uictx.vert_start ); + + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vg_uictx.ebo ); + glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, indice_offset, indice_size, + vg_uictx.indice_buffer+vg_uictx.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_uictx.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_uictx.indice_start*sizeof(u16)) ); + + glDisable( GL_BLEND ); + + vg_uictx.indice_start = vg_uictx.cur_indice; + vg_uictx.vert_start = vg_uictx.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_uictx.cur_vert + 4 > vg_uictx.max_verts) || + (vg_uictx.cur_indice + 6 > vg_uictx.max_indices)) + return; + + struct ui_vert *vertices = &vg_uictx.vertex_buffer[ vg_uictx.cur_vert ]; + u16 *indices = &vg_uictx.indice_buffer[ vg_uictx.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_uictx.cur_vert; + + u16 start = vg_uictx.cur_vert; + u32 mesh[] = { 0,2,1, 0,3,2 }; + + for( u32 i=0; i vg_uictx.max_verts) || + (vg_uictx.cur_indice + 24 > vg_uictx.max_indices)) + return; + + struct ui_vert *vertices = &vg_uictx.vertex_buffer[ vg_uictx.cur_vert ]; + u16 *indices = &vg_uictx.indice_buffer[ vg_uictx.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_uictx.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 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; +} + +static ui_px ui_text_line_width( const char *str ) +{ + int length = 0; + const char *_c = str; + char c; + + while( (c = *(_c ++)) ){ + if( c >= 32 && c <= 126 ) + length ++; + else if( c == '\n' ) + break; + } + + return length * 8; +} + +static ui_px ui_text_string_height( const char *str ) +{ + int height = 1; + const char *_c = str; + char c; + + while( (c = *(_c ++)) ){ + if( c == '\n' ) height ++; + } + + return height * 14; +} + +static ui_px ui_text_aligned_x( const char *str, ui_rect rect, ui_px scale, + enum ui_align align ) +{ + if( align == k_ui_align_left ){ + return rect[0]; + } + else{ + ui_px width = ui_text_line_width( str ) * scale; + + if( align == k_ui_align_right ) + return rect[0] + rect[2]-width; + else + return rect[0] + (rect[2]-width)/2; + } +} + +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 ) +{ + return ui_min( max, ui_max( a, min ) ); +} + +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]; + child_max[0] = child[0]+child[2]; + child_max[1] = child[1]+child[3]; + + clipped[0] = ui_clamp( child[0], parent[0], parent_max[0] ); + clipped[1] = ui_clamp( child[1], parent[1], parent_max[1] ); + clipped[2] = ui_clamp( child_max[0], parent[0], parent_max[0] ); + clipped[3] = ui_clamp( child_max[1], parent[1], parent_max[1] ); + + if( clipped[0] == clipped[2] || + clipped[1] == clipped[3] ) + return 0; + + clipped[2] -= clipped[0]; + clipped[3] -= clipped[1]; + + return 1; +} + +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] ) + { + return 1; + } + else + return 0; +} + +static int ui_click_down(void) +{ + if( vg_uictx.ignore_input_frames ) return 0; + + if( (vg_uictx.mouse_state[0] & SDL_BUTTON(SDL_BUTTON_LEFT)) && + !(vg_uictx.mouse_state[1] & SDL_BUTTON(SDL_BUTTON_LEFT)) ) + return 1; + else + return 0; +} + +static int ui_clicking(void) +{ + if( vg_uictx.ignore_input_frames ) return 0; + return vg_uictx.mouse_state[0] & SDL_BUTTON(SDL_BUTTON_LEFT); +} + +static int ui_click_up(void) +{ + if( vg_uictx.ignore_input_frames ) return 0; + if( (vg_uictx.mouse_state[1] & SDL_BUTTON(SDL_BUTTON_LEFT)) && + !(vg_uictx.mouse_state[0] & SDL_BUTTON(SDL_BUTTON_LEFT)) ) + return 1; + else + return 0; +} + +static void ui_prerender(void) +{ + int x, y; + vg_uictx.mouse_state[1] = vg_uictx.mouse_state[0]; + vg_uictx.mouse_state[0] = SDL_GetMouseState( &x, &y ); + vg_uictx.mouse[0] = x; + vg_uictx.mouse[1] = y; + + vg_uictx.cur_vert = 0; + vg_uictx.cur_indice = 0; + vg_uictx.vert_start = 0; + vg_uictx.indice_start = 0; + + if( vg_uictx.ignore_input_frames ){ + vg_uictx.ignore_input_frames --; + return; + } + + if( ui_click_down() ){ + vg_uictx.mouse_click[0] = vg_uictx.mouse[0]; + vg_uictx.mouse_click[1] = vg_uictx.mouse[1]; + } +} + +static void ui_text( ui_rect rect, const char *str, ui_px scale, + enum ui_align align ) +{ + ui_rect text_cursor; + u32 current_colour = 0x00ffffff; + + const char *_c = str; + u8 c; + + 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; + + if( align & (k_ui_align_middle|k_ui_align_bottom) ){ + ui_px height = ui_text_string_height( str ) * scale; + + if( align & k_ui_align_bottom ) + text_cursor[1] += rect[3]-height; + else + text_cursor[1] += (rect[3]-height)/2; + } + + while( (c = *(_c ++)) ){ + if( c == '\n' ){ + text_cursor[1] += 14*scale; + text_cursor[0] = ui_text_aligned_x( _c, rect, scale, align ); + 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, current_colour, (ui_px[4]) + { + glyph_base[0]+2, + glyph_base[1]+1, + glyph_base[0]+6, + glyph_base[1]+8 + }); + } + } + else if( c == '\x1B' ){ + /* vt codes */ + _c ++; + u16 colour_id = 0; + for( int i=0; i<3; i ++ ){ + if( _c[i] ){ + if( _c[i] == 'm' ){ + _c = _c + i + 1; + + switch( colour_id ){ + case '0': current_colour = 0x00ffffff; break; + case '3'|'1'<<8: current_colour = 0x00201fee; break; + case '3'|'2'<<8: current_colour = 0x0037e420; break; + case '3'|'3'<<8: current_colour = 0x000ed8e2; break; + case '3'|'4'<<8: current_colour = 0x00f15010; break; + case '3'|'5'<<8: current_colour = 0x00ee20ee; break; + case '3'|'6'<<8: current_colour = 0x00eeee20; break; + case '3'|'7'<<8: current_colour = 0x00ffffff; break; + } + + break; + } + + colour_id |= _c[i] << (i*8); + } + else{ + _c = _c +i; + break; + } + } + + continue; + } + else if( c == '\t' ){ + text_cursor[0] += UI_GLYPH_SPACING_X*scale*4; + continue; + } + + text_cursor[0] += UI_GLYPH_SPACING_X*scale; + } +} + +static void ui_image( ui_rect rect, GLuint image ) +{ + ui_flush( k_ui_shader_colour ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, image ); + ui_fill_rect( rect, 0xffffffff, (ui_px[4]){ 0,0, 255,255 } ); + ui_flush( k_ui_shader_image ); +} + +static u32 v4f_u32_colour( v4f colour ) +{ + u32 r = colour[0] * 255.0f, + g = colour[1] * 255.0f, + b = colour[2] * 255.0f, + a = colour[3] * 255.0f; + + return r | (g<<8) | (b<<16) | (a<<24); +} + +static int ui_button( ui_rect rect, v4f colour ) +{ + int clickup= ui_click_up(), + click = ui_clicking() | clickup, + target = ui_inside_rect( rect, vg_uictx.mouse_click ) && click, + hover = ui_inside_rect( rect, vg_uictx.mouse ); + + u32 basecolour = v4f_u32_colour( colour ); + + if( click ){ + if( target ){ + if( hover ){ + if( clickup ){ + ui_fill( rect, 0xffffffff ); + vg_uictx.ignore_input_frames = 2; + rect_copy( rect, vg_uictx.click_fader ); + vg_uictx.click_fade_opacity = 1.0f; + return 1; + } + else{ + ui_fill( rect, 0xffcccccc ); + return 0; + } + } + else{ + ui_fill( rect, 0xff505050 ); + ui_outline( rect, 1, 0xffffffff ); + return 0; + } + } + else{ + ui_fill( rect, 0xff505050 ); + return 0; + } + } + else{ + if( hover ){ + ui_fill( rect, 0xffa0a0a0 ); + return 0; + } + else{ + ui_fill( rect, 0xff505050 ); + return 0; + } + } +} + +static int ui_button_text( ui_rect rect, const char *string, ui_px scale, + v4f colour ) +{ + int result = ui_button( rect, colour ); + ui_rect t = { 0,0, ui_text_line_width( string )*scale, 14*scale }; + ui_rect_center( rect, t ); + ui_text( t, string, scale, k_ui_align_left ); + return result; +} + +static void ui_postrender(void) +{ + if( vg_uictx.click_fade_opacity > 0.0f ){ + + float scale = vg_uictx.click_fade_opacity; + scale = vg_maxf( 1.0f/255.0f, scale*scale ); + + vg_uictx.click_fade_opacity -= vg.time_frame_delta * 1.8f; + u32 colour = v4f_u32_colour( (v4f){ 1.0f,1.0f,1.0f, scale } ); + + ui_rect rect; + rect[3] = (float)(vg_uictx.click_fader[3]) * scale; + rect[2] = vg_uictx.click_fader[2]; + ui_rect_center( vg_uictx.click_fader, rect ); + + ui_fill( rect, colour ); + } + ui_flush( k_ui_shader_colour ); +} + +#endif /* VG_IMGUI_H */ diff --git a/vg_loader.h b/vg_loader.h index f6f3a26..3c519b5 100644 --- a/vg_loader.h +++ b/vg_loader.h @@ -128,6 +128,7 @@ VG_STATIC void _vg_loader_free(void) VG_STATIC void _vg_render_log(void) { +#if 0 ui_begin( vg.window_x, vg.window_y ); SDL_AtomicLock( &log_print_sl ); @@ -157,6 +158,7 @@ VG_STATIC void _vg_render_log(void) ui_resolve(); ui_draw( NULL ); +#endif } VG_STATIC void _vg_loader_render_ring( float opacity ) diff --git a/vg_profiler.h b/vg_profiler.h index ca79e18..bfdde12 100644 --- a/vg_profiler.h +++ b/vg_profiler.h @@ -58,6 +58,7 @@ VG_STATIC void vg_profile_end( struct vg_profile *profile ) } } +#if 0 VG_STATIC void vg_profile_drawn( struct vg_profile **profiles, u32 count, float budget, ui_rect panel, u32 colour_offset ) { @@ -134,6 +135,7 @@ VG_STATIC void vg_profile_drawn( struct vg_profile **profiles, u32 count, k_text_align_left ); } } +#endif VG_STATIC void vg_profiler_init(void) { diff --git a/vg_ui.h b/vg_ui.h index 3c16711..5296afc 100644 --- a/vg_ui.h +++ b/vg_ui.h @@ -1,5 +1,6 @@ /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ +#if 0 #ifndef VG_UI_H #define VG_UI_H @@ -977,3 +978,4 @@ VG_STATIC void ui_checkbox( struct ui_checkbox *cb ) } #endif /* VG_UI_H */ +#endif