-/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
-
-#if 0
-#ifndef VG_UI_H
-#define VG_UI_H
-
-#define VG_GAME
-#include "vg/vg.h"
-#include "vg/vg_tex.h"
-#include "vg/vg_shader.h"
-
-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;"
- "layout (location=3) in vec4 a_clip;"
- "uniform mat3 uPv;"
- ""
- "out vec2 aTexCoords;"
- "out vec4 aColour;"
- "out vec2 aWsp;"
- "out vec4 aClip;"
- ""
- "void main()"
- "{"
- "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );"
- "aTexCoords = a_uv * 0.0078125;"
- "aColour = a_colour;"
-
- "aWsp = a_co;"
- "aClip = a_clip;"
- "}",
- },
- .fs =
- {
- .orig_file = NULL,
- .static_src =
- "uniform sampler2D uTexGlyphs;"
- "out vec4 FragColor;"
- ""
- "in vec2 aTexCoords;"
- "in vec4 aColour;"
- ""
- "in vec2 aWsp;"
- "in vec4 aClip;"
- ""
- "void main()"
- "{"
- "float clip_blend = step( aWsp.x, aClip.z ) *"
- "step( aWsp.y, aClip.w ) *"
- "step( aClip.x, aWsp.x ) *"
- "step( aClip.y, aWsp.y ); "
-
- "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*clip_blend );"
- "}"
- }
-};
-
-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;"
- "layout (location=3) in vec4 a_clip;"
- "uniform mat3 uPv;"
- ""
- "out vec2 aTexCoords;"
- "out vec4 aColour;"
- "out vec2 aWsp;"
- "out vec4 aClip;"
- ""
- "void main()"
- "{"
- "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );"
- "aTexCoords = a_uv * 0.0078125;"
- "aColour = a_colour;"
-
- "aWsp = a_co;"
- "aClip = a_clip;"
- "}",
- },
- .fs =
- {
- .orig_file = NULL,
- .static_src =
- "uniform sampler2D uTexImage;"
- "out vec4 FragColor;"
- ""
- "in vec2 aTexCoords;"
- "in vec4 aColour;"
- ""
- "in vec2 aWsp;"
- "in vec4 aClip;"
-
- "void main()"
- "{"
- "float clip_blend = step( aWsp.x, aClip.z ) *"
- "step( aWsp.y, aClip.w ) *"
- "step( aClip.x, aWsp.x ) *"
- "step( aClip.y, aWsp.y ); "
-
- "vec4 colour = texture( uTexImage, aTexCoords );"
- "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, clip_blend );"
- "}"
- }
-};
-
-typedef i16 ui_px;
-typedef u32 ui_colour;
-typedef ui_px ui_rect[4];
-typedef struct ui_colourset ui_colourset;
-
-/* Relative to cursor p0 */
-enum ui_text_align
-{
- k_text_align_left = 0,
- k_text_align_right = 1,
- k_text_align_center = 2
-};
-
-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;
- };
- };
-};
-
-#pragma pack(push,1)
-struct ui_vert
-{
- ui_px co[2];
- u8 uv[2];
- u32 colour;
- ui_rect clip;
-};
-#pragma pack(pop)
-
-struct
-{
- struct ui_qnode
- {
- ui_rect rect;
- ui_colour colour;
- int mouse_over;
- int capture_id;
- }
- stack[ 32 ];
-
- u32 control_id;
-
- struct ui_vert *vertex_buffer;
- u16 *indice_buffer;
- u32 max_verts, max_indices, cur_vert, cur_indice;
-
- ui_rect clipping;
- ui_rect cursor;
- u32 stack_count;
- u32 capture_mouse_id;
- int capture_lock;
-
- /* User input */
- ui_px mouse[2];
- int click_state; /* 0: released, 1: on down, 2: pressed, 3: on release */
-
- ui_colourset *colours;
-
- GLuint vao;
- GLuint vbo;
- GLuint ebo;
-
- struct ui_image
- {
- ui_rect rc;
- GLuint image;
- }
- images[16];
- int image_count;
-}
-static vg_uictx;
-
-#define UI_GLYPH_SPACING_X 8
-
-static GLuint ui_glyph_texture = 0;
-static ui_colourset ui_default_colours = {
- .main = 0xff807373,
- .hover = 0xff918484,
- .active = 0xffad9f9e
-};
-
-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;
- vg_uictx.colours = &ui_default_colours;
-
- /* 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 );
-
- /* CLIPPING */
- glVertexAttribPointer( 3, 4, GL_SHORT, GL_FALSE, stride,
- (void *)offsetof( struct ui_vert, clip ) );
- glEnableVertexAttribArray( 3 );
-
- 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, &ui_glyph_texture );
- glBindTexture( GL_TEXTURE_2D, ui_glyph_texture );
- 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 );
-}
-
-static struct ui_vert *ui_fill_rect_uv( ui_rect rect, u32 colour, ui_px uv[4] );
-
-VG_STATIC void ui_draw( m3x3f view_override )
-{
- u32 num_indices_normal = vg_uictx.cur_indice;
-
- /* Append images to back of buffer */
- for( int i = 0; i < vg_uictx.image_count; i ++ )
- {
- ui_fill_rect_uv( vg_uictx.images[i].rc, 0xffffffff,
- (ui_px[4]){0,0,128,128} );
- }
-
- glBindVertexArray( vg_uictx.vao );
-
- glBindBuffer( GL_ARRAY_BUFFER, vg_uictx.vbo );
- glBufferSubData( GL_ARRAY_BUFFER, 0,
- vg_uictx.cur_vert * sizeof( struct ui_vert ),
- vg_uictx.vertex_buffer );
-
- glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vg_uictx.ebo );
- glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, 0,
- vg_uictx.cur_indice * sizeof( u16 ),
- vg_uictx.indice_buffer );
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBlendEquation(GL_FUNC_ADD);
-
- glUseProgram( _shader_ui.id );
-
- m3x3f view = M3X3_IDENTITY;
-
- if( !view_override )
- {
- view_override = view;
-
- 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 } );
- }
-
- /* TODO? */
- glUniformMatrix3fv( glGetUniformLocation( _shader_ui.id, "uPv" ), 1,
- GL_FALSE, (float *)view_override );
-
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, ui_glyph_texture );
- glUniform1i( glGetUniformLocation( _shader_ui.id, "uTexGlyphs" ), 0 );
-
- glDrawElements( GL_TRIANGLES, num_indices_normal,
- GL_UNSIGNED_SHORT, (void*)(0) );
-
-
- /* images */
- glUseProgram( _shader_ui_image.id );
- glUniformMatrix3fv( glGetUniformLocation( _shader_ui_image.id, "uPv" ), 1,
- GL_FALSE, (float *)view_override );
-
- glActiveTexture( GL_TEXTURE1 );
- glUniform1i( glGetUniformLocation( _shader_ui_image.id, "uTexImage" ), 1 );
-
- /* Draw image elements */
- for( int i = 0; i < vg_uictx.image_count; i ++ )
- {
- struct ui_image *img = &vg_uictx.images[i];
-
- glBindTexture( GL_TEXTURE_2D, img->image );
- glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
- (void*)( (num_indices_normal + 6*i)*sizeof(u16) ) );
- }
-
- glDisable(GL_BLEND);
-}
-
-/*
- * Rect controls
- */
-VG_STATIC void ui_rect_copy( ui_rect src, ui_rect dst )
-{
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
- dst[3] = src[3];
-}
-
-VG_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;
-}
-
-/*
- * Stack control
- */
-static struct ui_qnode *ui_current(void)
-{
- return &vg_uictx.stack[ vg_uictx.stack_count-1 ];
-}
-
-VG_STATIC void ui_new_node(void)
-{
- if( vg_uictx.stack_count == vg_list_size( vg_uictx.stack ) )
- {
- vg_error( "[UI] Stack overflow while creating box!" );
- return;
- }
-
- struct ui_qnode *parent = &vg_uictx.stack[ vg_uictx.stack_count-1 ];
- struct ui_qnode *node = &vg_uictx.stack[ vg_uictx.stack_count++ ];
- ui_rect_copy( vg_uictx.cursor, node->rect );
-
- if( parent->mouse_over )
- {
- if( vg_uictx.mouse[0] >= node->rect[0] &&
- vg_uictx.mouse[0] < node->rect[0]+node->rect[2] &&
- vg_uictx.mouse[1] >= node->rect[1] &&
- vg_uictx.mouse[1] < node->rect[1]+node->rect[3] )
- node->mouse_over = 1;
- else
- node->mouse_over = 0;
- }
- else
- {
- node->mouse_over = 0;
- }
-}
-
-static int ui_hasmouse(void)
-{
- struct ui_qnode *node = ui_current();
- return (node->mouse_over && (node->capture_id == vg_uictx.capture_mouse_id));
-}
-
-VG_STATIC void ui_end(void)
-{
- struct ui_qnode *node = &vg_uictx.stack[ --vg_uictx.stack_count ];
- ui_rect_copy( node->rect, vg_uictx.cursor );
-}
-
-VG_STATIC void ui_end_down(void)
-{
- ui_px height = ui_current()->rect[3];
- ui_end();
- vg_uictx.cursor[1] += height;
-}
-
-VG_STATIC void ui_end_right(void)
-{
- ui_px width = ui_current()->rect[2];
- ui_end();
- vg_uictx.cursor[0] += width;
-}
-
-VG_STATIC void ui_fill_y(void)
-{
- struct ui_qnode *node = ui_current();
- vg_uictx.cursor[3] = node->rect[3] - (vg_uictx.cursor[1]-node->rect[1]);
-}
-
-VG_STATIC void ui_fill_x(void)
-{
- struct ui_qnode *node = ui_current();
- vg_uictx.cursor[2] = node->rect[2] - (vg_uictx.cursor[0]-node->rect[0]);
-}
-
-VG_STATIC void ui_align_bottom(void)
-{
- struct ui_qnode *node = ui_current();
- vg_uictx.cursor[1] = node->rect[1] + node->rect[3] - vg_uictx.cursor[3];
-}
-
-VG_STATIC void ui_align_right(void)
-{
- struct ui_qnode *node = ui_current();
- vg_uictx.cursor[0] = node->rect[0] + node->rect[2] - vg_uictx.cursor[2];
-}
-
-VG_STATIC void ui_align_top(void)
-{
- vg_uictx.cursor[1] = ui_current()->rect[1];
-}
-
-VG_STATIC void ui_align_left(void)
-{
- vg_uictx.cursor[0] = ui_current()->rect[0];
-}
-
-VG_STATIC void ui_clamp_rect( ui_rect parent, ui_rect dest )
-{
- dest[0] = vg_min( parent[0] + parent[2] - dest[2], dest[0] );
- dest[1] = vg_min( parent[1] + parent[3] - dest[3], dest[1] );
- dest[0] = vg_max( parent[0], dest[0] );
- dest[1] = vg_max( parent[1], dest[1] );
-}
-
-VG_STATIC void ui_capture_mouse( u32 id )
-{
- struct ui_qnode *node = &vg_uictx.stack[ vg_uictx.stack_count-1 ];
- node->capture_id = id;
-
- if( !vg_uictx.capture_lock && node->mouse_over )
- {
- vg_uictx.capture_mouse_id = id;
- }
-}
-
-static int ui_want_mouse(void)
-{
- return vg_uictx.capture_mouse_id == 0? 0: 1;
-}
-
-VG_STATIC void ui_set_clip( ui_rect clip )
-{
- vg_uictx.clipping[0] = clip[0];
- vg_uictx.clipping[1] = clip[1];
- vg_uictx.clipping[2] = clip[0] + clip[2];
- vg_uictx.clipping[3] = clip[1] + clip[3];
-}
-
-VG_STATIC void ui_release_clip(void)
-{
- vg_uictx.clipping[0] = -32000;
- vg_uictx.clipping[1] = -32000;
- vg_uictx.clipping[2] = 32000;
- vg_uictx.clipping[3] = 32000;
-}
-
-static struct ui_vert *ui_fill_rect_uv( ui_rect rect, u32 colour, ui_px uv[4] )
-{
- /* this if far from ideal but stops us from crashing */
- if( (vg_uictx.cur_vert + 6 > vg_uictx.max_verts) ||
- (vg_uictx.cur_indice + 4 > vg_uictx.max_indices))
- return vg_uictx.vertex_buffer;
-
- struct ui_vert *vertices = &vg_uictx.vertex_buffer[ vg_uictx.cur_vert ];
- u16 *indices = &vg_uictx.indice_buffer[ vg_uictx.cur_indice ];
-
- 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[0].colour = colour;
- 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[1].colour = colour;
- 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[2].colour = colour;
- 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];
- vertices[3].colour = colour;
- u16 ind_start = vg_uictx.cur_vert;
-
- ui_rect_copy( vg_uictx.clipping, vertices[0].clip );
- ui_rect_copy( vg_uictx.clipping, vertices[1].clip );
- ui_rect_copy( vg_uictx.clipping, vertices[2].clip );
- ui_rect_copy( vg_uictx.clipping, vertices[3].clip );
-
- indices[0] = ind_start+0;
- indices[1] = ind_start+2;
- indices[2] = ind_start+1;
-
- indices[3] = ind_start+0;
- indices[4] = ind_start+3;
- indices[5] = ind_start+2;
-
- vg_uictx.cur_indice += 6;
- vg_uictx.cur_vert += 4;
-
- return vertices;
-}
-
-static struct ui_vert *ui_fill_rect( ui_rect rect, u32 colour )
-{
- return ui_fill_rect_uv( rect, colour, (ui_px[4]){ 4,4, 4,4 } );
-}
-
-static ui_px ui_text_line_offset( const char *str, ui_px scale,
- enum ui_text_align align )
-{
- if( align == k_text_align_left )
- return 0;
-
- int length = 0;
- const char *_c = str;
- char c;
-
- while( (c = *(_c ++)) )
- if( c >= 32 && c <= 126 )
- length ++;
- else if( c == '\n' )
- break;
-
- if( align == k_text_align_right )
- return -length * scale*8;
- else
- return (-length * scale*8) / 2;
-}
-
-VG_STATIC void ui_text( ui_px pos[2],
- const char *str, ui_px scale, enum ui_text_align align )
-{
- ui_rect text_cursor;
- u32 current_colour = 0x00ffffff;
-
- const char *_c = str;
- u8 c;
-
- text_cursor[0] = pos[0] + ui_text_line_offset( str, scale, align );
- text_cursor[1] = pos[1];
- text_cursor[2] = 8*scale;
- text_cursor[3] = 14*scale;
-
- while( (c = *(_c ++)) ){
- if( c == '\n' ){
- text_cursor[1] += 14*scale;
- text_cursor[0] = pos[0] + ui_text_line_offset( _c, 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_fill_rect_uv( text_cursor, 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' ){
- _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;
- }
-}
-
-/*
- * API Control
- */
-VG_STATIC void ui_begin( ui_px res_x, ui_px res_y )
-{
- vg_uictx.cursor[0] = 0;
- vg_uictx.cursor[1] = 0;
- vg_uictx.cursor[2] = res_x;
- vg_uictx.cursor[3] = res_y;
-
- ui_rect_copy( vg_uictx.cursor, vg_uictx.stack[0].rect );
- vg_uictx.stack[0].mouse_over = 1;
-
- vg_uictx.stack_count = 1;
-
- vg_uictx.cur_vert = 0;
- vg_uictx.cur_indice = 0;
-
- ui_release_clip();
-
- if( vg_uictx.click_state == 0 )
- vg_uictx.capture_mouse_id = 0;
-
- vg_uictx.image_count = 0;
-}
-
-VG_STATIC void ui_resolve(void)
-{
- if( vg_uictx.stack_count-1 )
- {
- vg_error( "[UI] Mismatched node create/drestroy!" );
- return;
- }
-
- if( vg_uictx.click_state == 3 || vg_uictx.click_state == 0 )
- {
- vg_uictx.capture_lock = 0;
- }
-}
-
-VG_STATIC void ui_set_mouse( int x, int y, int click_state )
-{
- vg_uictx.mouse[0] = x;
- vg_uictx.mouse[1] = y;
-
- vg_uictx.click_state = click_state;
-}
-
-/*
- * High level controls
- */
-struct ui_window
-{
- const char *title;
- ui_rect transform;
-
- int drag;
- ui_px drag_offset[2];
-};
-
-enum button_state
-{
- k_button_released = 0,
- k_button_start_click,
- k_button_click,
- k_button_hold
-};
-
-static int ui_button(void)
-{
- u32 uid = vg_uictx.control_id ++;
-
- ui_new_node();
- {
- ui_capture_mouse( uid );
-
- if( ui_hasmouse() )
- {
- ui_fill_rect( vg_uictx.cursor, vg_uictx.colours->hover );
-
- if( vg_uictx.click_state == 1 )
- {
- vg_uictx.capture_lock = 1;
- return k_button_start_click;
- }
- else if( vg_uictx.capture_lock && vg_uictx.click_state == 3 )
- return k_button_click;
- else if( vg_uictx.capture_lock && vg_uictx.click_state == 2 )
- return k_button_hold;
-
- return k_button_click;
- }
- else
- ui_fill_rect( vg_uictx.cursor, vg_uictx.colours->main );
- }
-
- return k_button_released;
-}
-
-static int ui_window( struct ui_window *window, u32 control_group )
-{
- if( window->drag )
- {
- window->transform[0] = vg_uictx.mouse[0]+window->drag_offset[0];
- window->transform[1] = vg_uictx.mouse[1]+window->drag_offset[1];
-
- ui_clamp_rect( vg_uictx.stack[0].rect, window->transform );
-
- if( vg_uictx.click_state == 0 || vg_uictx.click_state == 3 )
- {
- window->drag = 0;
- }
- }
-
- ui_rect_copy( window->transform, vg_uictx.cursor );
-
- ui_new_node();
- {
- ui_capture_mouse( vg_uictx.control_id ++ );
-
- /* Drag bar */
- vg_uictx.cursor[3] = 25;
- ui_new_node();
- {
- ui_capture_mouse( vg_uictx.control_id ++ );
-
- struct ui_vert *drag_bar = ui_fill_rect( vg_uictx.cursor, 0xff555555 );
-
- /* title.. */
- vg_uictx.cursor[0] += 2;
- vg_uictx.cursor[1] += 2;
- ui_text( vg_uictx.cursor, window->title, 2, 0 );
-
- /* Close button */
- vg_uictx.cursor[3] = 25;
- vg_uictx.cursor[2] = 25;
- ui_align_right();
- ui_align_top();
- ui_rect_pad( vg_uictx.cursor, 4 );
-
- if( ui_button() )
- {
- vg_info( "Click clacked\n" );
- }
- vg_uictx.cursor[0] += 2;
- ui_text( vg_uictx.cursor, "x", 2, 0 );
- ui_end();
-
- if( ui_hasmouse() )
- {
- drag_bar[0].colour = 0xff777777;
- drag_bar[1].colour = 0xff777777;
- drag_bar[2].colour = 0xff777777;
- drag_bar[3].colour = 0xff777777;
-
- /* start drag */
- if( vg_uictx.click_state == 1 )
- {
- window->drag = 1;
- window->drag_offset[0] = window->transform[0]-vg_uictx.mouse[0];
- window->drag_offset[1] = window->transform[1]-vg_uictx.mouse[1];
- }
- }
- }
- ui_end_down();
- }
-
- return 1;
-}
-
-VG_STATIC void ui_push_image( ui_rect rc, GLuint image )
-{
- struct ui_image *img = &vg_uictx.images[ vg_uictx.image_count ++ ];
- ui_rect_copy( rc, img->rc );
- img->image = image;
-}
-
-struct ui_slider
-{
- float *data;
- float min, max;
-};
-
-struct ui_slider_vector
-{
- float *data, min, max;
- struct ui_slider sub[4];
- u32 len;
-};
-
-struct ui_checkbox
-{
- int *data;
-};
-
-VG_STATIC void ui_slider( struct ui_slider *slider )
-{
- ui_new_node();
-
- ui_px slider_start = vg_uictx.cursor[0];
-
- float const ftotal = vg_uictx.cursor[2],
- fwidth = ftotal*0.25f,
- fmove = ftotal - fwidth,
- fstart = fwidth*0.5f,
- frange = slider->max-slider->min,
- fpos = (*slider->data - slider->min) / frange;
-
- ui_fill_rect( vg_uictx.cursor, 0xff111111 );
- vg_uictx.cursor[2] = fwidth;
- vg_uictx.cursor[0] = slider_start + fpos * fmove;
-
- u32 uid = vg_uictx.control_id ++;
- int status = ui_button();
- if( vg_uictx.capture_lock && (vg_uictx.capture_mouse_id == uid))
- {
- float ui_new = vg_uictx.mouse[0],
- local = ui_new - (slider_start + fstart),
- zo = vg_clampf(local / fmove,0.0f,1.0f);
-
- *slider->data = vg_lerpf( slider->min, slider->max, zo );
- }
-
- vg_uictx.cursor[0] += 4;
- vg_uictx.cursor[1] += 4;
-
- char buf[12];
- snprintf( buf, 12, "%.2f", *slider->data );
- ui_text( vg_uictx.cursor, buf, 1, 0 );
- ui_end_down();
- ui_end_down();
-}
-
-VG_STATIC void ui_slider_vector( struct ui_slider_vector *slider )
-{
- for( int i=0; i<slider->len; i++ )
- {
- slider->sub[i].data = &slider->data[i];
- slider->sub[i].min = slider->min;
- slider->sub[i].max = slider->max;
- ui_slider( &slider->sub[i] );
- }
-}
-
-VG_STATIC void ui_checkbox( struct ui_checkbox *cb )
-{
- if( ui_button() == k_button_click )
- *cb->data ^= 0x1;
-
- ui_new_node();
- ui_rect_pad( vg_uictx.cursor, 4 );
- if( *cb->data )
- ui_fill_rect( vg_uictx.cursor, 0xff00e052 );
- else
- ui_fill_rect( vg_uictx.cursor, 0xff0052e0 );
-
- ui_end();
- ui_end_down();
-}
-
-#endif /* VG_UI_H */
-#endif