imgui stuff
authorhgn <hgodden00@gmail.com>
Sun, 30 Apr 2023 18:22:02 +0000 (19:22 +0100)
committerhgn <hgodden00@gmail.com>
Sun, 30 Apr 2023 18:22:02 +0000 (19:22 +0100)
submodules/SDL
vg.h
vg_audio.h
vg_console.h
vg_imgui.h [new file with mode: 0644]
vg_loader.h
vg_profiler.h
vg_ui.h

index eef4d3c86a653f91b7221c80809ba8ab56f94cf1..06492c598158cf825a18aececaf7511d7fd04f48 160000 (submodule)
@@ -1 +1 @@
-Subproject commit eef4d3c86a653f91b7221c80809ba8ab56f94cf1
+Subproject commit 06492c598158cf825a18aececaf7511d7fd04f48
diff --git a/vg.h b/vg.h
index ecb75505d6ec9985cde486a6a0516a99d61b6303..a89d750d80aaf9c7cbad96a188e08d85dcf38cd5 100644 (file)
--- 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 */
index 0e76efd3e4959b8808807a4ee69daa53b97f0046..120622cc658307bcb15239b88b08f9c8b733d584 100644 (file)
@@ -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();
 }
index d5da84729b2f5e770baf1863c3b8406aaf4f73ef..8d47210aa593ae1df8308b3e4ec3bbeb2dfeaf79 100644 (file)
@@ -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 (file)
index 0000000..d843cdc
--- /dev/null
@@ -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_list_size(mesh); i++ ){
+      indices[i] = start+mesh[i];
+   }
+
+       vg_uictx.cur_indice += 6;
+       vg_uictx.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_uictx.cur_vert + 8 > 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<vg_list_size(mesh); i++ ){
+      indices[i] = start+mesh[i];
+   }
+       
+       vg_uictx.cur_indice += 24;
+       vg_uictx.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;
+}
+
+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 a<b?a:b; }
+static ui_px ui_max( ui_px a, ui_px b ){ return a>b?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 */
index f6f3a26f8b1758a6d8ab1d0b25d71b0b45f51632..3c519b57137bc99d19707c80b07c421e1c178079 100644 (file)
@@ -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 )
index ca79e18d0bf77df3da6421de40176b916ff83d5c..bfdde127af5b921840a79b66aa7c57c7367996be 100644 (file)
@@ -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 3c16711619139ef0fb31a3886bf9f06829b16d3e..5296afc12e76b5f95c4f36c64e663483bda44904 100644 (file)
--- 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