-// Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
+/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
SHADER_DEFINE( shader_ui,
- // VERTEX
- "layout (location=0) in vec2 a_co;" // i16, i16, .. ?
- "layout (location=1) in vec2 a_uv;" // i16, i16
- "layout (location=2) in vec4 a_colour;" // u32
- "layout (location=3) in vec4 a_clip;" // i16, i16, i16, i16
+ "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;"
"aClip = a_clip;"
"}",
- // FRAGMENT
+ /* Fragment */
"uniform sampler2D uTexGlyphs;"
"out vec4 FragColor;"
""
""
"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 );"
+ "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 )"
UNIFORMS({ "uPv", "uTexGlyphs" })
)
-// Types
-// ===========================================================================================================
-
typedef i16 ui_px;
typedef u32 ui_colour;
typedef ui_px ui_rect[4];
typedef struct ui_ctx ui_ctx;
typedef struct ui_colourset ui_colourset;
-// Relative to cursor p0
+/* Relative to cursor p0 */
enum ui_text_align
{
k_text_align_left = 0,
#pragma pack(push,1)
struct ui_vert
{
- ui_px co[2]; //32 4
- u8 uv[2]; //16 2
- u32 colour; //32 4
- ui_rect clip; //64 8
+ ui_px co[2];
+ u8 uv[2];
+ u32 colour;
+ ui_rect clip;
}
*verts;
#pragma pack(pop)
u32 id_base;
int glyph_base;
- // User input
+ /* User input */
ui_px mouse[2];
- int click_state; // 0: released, 1: on down, 2: pressed, 3: on release
+ int click_state; /* 0: released, 1: on down, 2: pressed, 3: on release */
ui_colourset *colours;
int image_count;
};
-// Globals
-// ===========================================================================================================
-
#define UI_GLYPH_SPACING_X 9
static GLuint ui_glyph_texture = 0;
static ui_ctx ui_global_ctx;
-// Initialization
-// ===========================================================================================================
-
static void ui_init_context( ui_ctx *ctx, int index_buffer_size )
{
u32 vertex_buffer_size = (index_buffer_size+(index_buffer_size/2));
- // Generate the buffer we are gonna be drawing to
+ /* Generate the buffer we are gonna be drawing to */
{
glGenVertexArrays(1, &ctx->vao);
glGenBuffers( 1, &ctx->vbo );
glBindBuffer( GL_ARRAY_BUFFER, ctx->vbo );
- glBufferData( GL_ARRAY_BUFFER, vertex_buffer_size * sizeof( struct ui_vert ), NULL, GL_DYNAMIC_DRAW );
+ glBufferData( GL_ARRAY_BUFFER,
+ vertex_buffer_size * sizeof( struct ui_vert ),
+ NULL, GL_DYNAMIC_DRAW );
glBindVertexArray( ctx->vao );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ctx->ebo );
- glBufferData( GL_ELEMENT_ARRAY_BUFFER, index_buffer_size * sizeof( u16 ), NULL, GL_DYNAMIC_DRAW );
+ glBufferData( GL_ELEMENT_ARRAY_BUFFER,
+ index_buffer_size * sizeof( u16 ), NULL, GL_DYNAMIC_DRAW );
u32 const stride = sizeof( struct ui_vert );
- // XY
- glVertexAttribPointer( 0, 2, GL_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, co ) );
+ /* 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 ) );
+ /* 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 ) );
+ /* 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 ) );
+ /* CLIPPING */
+ glVertexAttribPointer( 3, 4, GL_SHORT, GL_FALSE, stride,
+ (void *)offsetof( struct ui_vert, clip ) );
glEnableVertexAttribArray( 3 );
}
- // Initialize default context
+ /* Initialize default context */
{
- ctx->verts = (struct ui_vert *)malloc( vertex_buffer_size * sizeof(struct ui_vert) );
+ ctx->verts = (struct ui_vert *)malloc(
+ vertex_buffer_size * sizeof(struct ui_vert) );
ctx->indices = (u16*)malloc( index_buffer_size * sizeof(u16) );
if( !ctx->colours )
static void ui_default_init(void)
{
- // Load default font
+ /* Load default font */
u32 compressed[] = {
#include "vg/vg_pxfont.h"
};
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 );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, 256, 256, 0,
+ GL_RED, GL_UNSIGNED_BYTE, image );
vg_tex2d_clamp();
vg_tex2d_nearest();
free( image );
- // Setup OpenGL memory
SHADER_INIT( shader_ui );
ui_init_context( &ui_global_ctx, 20000 );
}
ui_context_free( &ui_global_ctx );
}
-static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect, u32 colour, ui_px uv[4] );
+static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect,
+ u32 colour, ui_px uv[4] );
+
static void ui_draw( ui_ctx *ctx, m3x3f view_override )
{
u32 num_indices_normal = ctx->num_indices;
- // Append images to back of buffer
+ /* Append images to back of buffer */
for( int i = 0; i < ctx->image_count; i ++ )
- ui_fill_rect_uv( ctx, ctx->images[i].rc, 0xffffffff, (ui_px[4]){0,0,128,128} );
+ {
+ ui_fill_rect_uv( ctx, ctx->images[i].rc,
+ 0xffffffff, (ui_px[4]){0,0,128,128} );
+ }
glBindVertexArray( ctx->vao );
glBindBuffer( GL_ARRAY_BUFFER, ctx->vbo );
- glBufferSubData( GL_ARRAY_BUFFER, 0, ctx->num_verts * sizeof( struct ui_vert ), ctx->verts );
+ glBufferSubData( GL_ARRAY_BUFFER, 0,
+ ctx->num_verts * sizeof( struct ui_vert ), ctx->verts );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ctx->ebo );
- glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, 0, ctx->num_indices * sizeof( u16 ), ctx->indices );
+ glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, 0,
+ ctx->num_indices * sizeof( u16 ), ctx->indices );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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 } );
+ m3x3_scale( view, (v3f){ 1.0f/((float)vg_window_x*0.5f),
+ -1.0f/((float)vg_window_y*0.5f), 1.0f } );
}
- glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1, GL_FALSE, (float *)view_override );
+ glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1,
+ GL_FALSE, (float *)view_override );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, ui_glyph_texture );
glUniform1i( SHADER_UNIFORM( shader_ui, "uTexGlyphs" ), 0 );
- glDrawElements( GL_TRIANGLES, num_indices_normal, GL_UNSIGNED_SHORT, (void*)(0) );
+ glDrawElements( GL_TRIANGLES, num_indices_normal,
+ GL_UNSIGNED_SHORT, (void*)(0) );
- // Draw image elements
+ /* Draw image elements */
for( int i = 0; i < ctx->image_count; i ++ )
{
struct ui_image *img = &ctx->images[i];
glBindTexture( GL_TEXTURE_2D, img->image );
- glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)( (num_indices_normal + 6*i)*sizeof(u16) ) );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
+ (void*)( (num_indices_normal + 6*i)*sizeof(u16) ) );
}
glDisable(GL_BLEND);
}
-// Rect controls
-// ===========================================================================================================
-
+/*
+ * Rect controls
+ */
static void ui_rect_copy( ui_rect src, ui_rect dst )
{
dst[0] = src[0];
rect[3] -= pad*2;
}
-// Stack control
-// ===========================================================================================================
-
+/*
+ * Stack control
+ */
static struct ui_qnode *ui_current( ui_ctx *ctx )
{
return &ctx->stack[ ctx->stack_count-1 ];
if( parent->mouse_over )
{
- if( ctx->mouse[0] >= node->rect[0] && ctx->mouse[0] < node->rect[0]+node->rect[2] &&
- ctx->mouse[1] >= node->rect[1] && ctx->mouse[1] < node->rect[1]+node->rect[3] )
+ if( ctx->mouse[0] >= node->rect[0] &&
+ ctx->mouse[0] < node->rect[0]+node->rect[2] &&
+ ctx->mouse[1] >= node->rect[1] &&
+ ctx->mouse[1] < node->rect[1]+node->rect[3] )
node->mouse_over = 1;
else
node->mouse_over = 0;
ctx->cursor[2] = node->rect[2] - (ctx->cursor[0]-node->rect[0]);
}
-// Alignment: | [] | -> | []|
static void ui_align_bottom( ui_ctx *ctx )
{
struct ui_qnode *node = ui_current( ctx );
ctx->clipping[3] = 32000;
}
-// Drawing
-// ===========================================================================================================
-
-static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect, u32 colour, ui_px uv[4] )
+static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect,
+ u32 colour, ui_px uv[4] )
{
struct ui_vert *vertices = &ctx->verts[ ctx->num_verts ];
vertices[0].co[0] = rect[0];
return ui_fill_rect_uv( ctx, 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 )
+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;
return (-length * scale*8) / 2;
}
-static void ui_text( ui_ctx *ctx, ui_px pos[2], const char *str, ui_px scale, enum ui_text_align align )
+static void ui_text( ui_ctx *ctx, ui_px pos[2],
+ const char *str, ui_px scale, enum ui_text_align align )
{
ui_rect text_cursor;
u32 current_colour = 0x00ffffff;
glyph_base[0] *= 8;
glyph_base[1] *= 8;
- ui_fill_rect_uv( ctx, text_cursor, current_colour, (ui_px[4]){glyph_base[0]+2,glyph_base[1]+1,glyph_base[0]+6,glyph_base[1]+8} );
+ ui_fill_rect_uv( ctx, 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' )
{
}
}
-// API control
-// ====================================================================
-
+/*
+ * API Control
+ */
static void ui_begin( ui_ctx *ctx, ui_px res_x, ui_px res_y )
{
ctx->cursor[0] = 0;
}
}
-// User Input piping
-// ====================================================================
-
static void ui_set_mouse( ui_ctx *ctx, int x, int y, int click_state )
{
ctx->mouse[0] = x;
ctx->click_state = click_state;
}
-// High level controls
-// ====================================================================
-
+/*
+ * High level controls
+ */
struct ui_window
{
const char *title;
{
ui_capture_mouse( ctx, __COUNTER__ );
- // Drag bar
+ /* Drag bar */
ctx->cursor[3] = 25;
ui_new_node( ctx );
{
struct ui_vert *drag_bar = ui_fill_rect( ctx, ctx->cursor, 0xff555555 );
- // title..
+ /* title.. */
ctx->cursor[0] += 2;
ctx->cursor[1] += 2;
ui_text( ctx, ctx->cursor, window->title, 2, 0 );
- // Close button
+ /* Close button */
ctx->cursor[3] = 25;
ctx->cursor[2] = 25;
ui_align_right( ctx );
drag_bar[2].colour = 0xff777777;
drag_bar[3].colour = 0xff777777;
- // start drag
+ /* start drag */
if( ctx->click_state == 1 )
{
window->drag = 1;
return 1;
}
-struct ui_scrollbar
-{
- int drag;
- ui_px drag_offset;
-
- ui_px py;
- ui_px bar_height;
- ui_px view_height;
-};
-
-static void ui_scrollbar( ui_ctx *ctx, struct ui_scrollbar *scrollbar, u32 id )
-{
- scrollbar->view_height = ctx->cursor[3];
-
- if( scrollbar->drag )
- {
- scrollbar->py = ctx->mouse[1]+scrollbar->drag_offset;
- scrollbar->py = VG_MAX( scrollbar->py, 0 );
- scrollbar->py = VG_MIN( scrollbar->py, ctx->cursor[3] - scrollbar->bar_height );
-
- if( ctx->click_state == 0 || ctx->click_state == 3 )
- scrollbar->drag = 0;
- }
-
- ui_new_node( ctx );
- {
- ui_fill_rect( ctx, ctx->cursor, ctx->colours->background );
- ui_capture_mouse( ctx, id );
-
- ctx->cursor[1] += scrollbar->py;
- ctx->cursor[3] = scrollbar->bar_height;
-
- ui_new_node( ctx );
- {
- ui_capture_mouse( ctx, __COUNTER__ );
- struct ui_vert *drag_bar = ui_fill_rect( ctx, ctx->cursor, ctx->colours->bar );
-
- if( ui_hasmouse( ctx ) || scrollbar->drag )
- {
- drag_bar[0].colour = ctx->colours->bar_hover;
- drag_bar[1].colour = ctx->colours->bar_hover;
- drag_bar[2].colour = ctx->colours->bar_hover;
- drag_bar[3].colour = ctx->colours->bar_hover;
-
- // start drag
- if( ctx->click_state == 1 )
- {
- scrollbar->drag = 1;
- scrollbar->drag_offset = scrollbar->py - ctx->mouse[1];
- }
- }
- }
- ui_end_down( ctx );
- }
- ui_end( ctx );
-}
-
-static ui_px ui_calculate_content_scroll( struct ui_scrollbar *scrollbar, ui_px content )
-{
- float overlap = vg_maxf( 0.0f, (float)(content - scrollbar->view_height) );
-
- float range = scrollbar->view_height - scrollbar->bar_height;
- return ((float)scrollbar->py / range) * overlap;
-}
-
static void ui_push_image( ui_ctx *ctx, ui_rect rc, GLuint image )
{
struct ui_image *img = &ctx->images[ ctx->image_count ++ ];
img->image = image;
}
-// Shortnames
+/* Shortnames */
#define gui_draw(...) ui_draw( &ui_global_ctx, __VA_ARGS__)
#define gui_current(...) ui_current( &ui_global_ctx, __VA_ARGS__)
#define gui_new_node() ui_new_node( &ui_global_ctx )
#define gui_window(...) ui_window( &ui_global_ctx, __VA_ARGS__)
#define gui_want_mouse() ui_want_mouse( &ui_global_ctx )
#define gui_push_image(...) ui_push_image( &ui_global_ctx, __VA_ARGS__ )
-#define gui_scrollbar(...) ui_scrollbar( &ui_global_ctx, __VA_ARGS__)
#define gui_reset_colours(...) ui_reset_colours( &ui_global_ctx )