--- /dev/null
+// stb_include.h - v0.02 - parse and process #include directives - public domain
+//
+// To build this, in one source file that includes this file do
+// #define STB_INCLUDE_IMPLEMENTATION
+//
+// This program parses a string and replaces lines of the form
+// #include "foo"
+// with the contents of a file named "foo". It also embeds the
+// appropriate #line directives. Note that all include files must
+// reside in the location specified in the path passed to the API;
+// it does not check multiple directories.
+//
+// If the string contains a line of the form
+// #inject
+// then it will be replaced with the contents of the string 'inject' passed to the API.
+//
+// Options:
+//
+// Define STB_INCLUDE_LINE_GLSL to get GLSL-style #line directives
+// which use numbers instead of filenames.
+//
+// Define STB_INCLUDE_LINE_NONE to disable output of #line directives.
+//
+// Standard libraries:
+//
+// stdio.h FILE, fopen, fclose, fseek, ftell
+// stdlib.h malloc, realloc, free
+// string.h strcpy, strncmp, memcpy
+//
+// Credits:
+//
+// Written by Sean Barrett.
+//
+// Fixes:
+// Michal Klos
+
+#ifndef STB_INCLUDE_STB_INCLUDE_H
+#define STB_INCLUDE_STB_INCLUDE_H
+
+// Do include-processing on the string 'str'. To free the return value, pass it to free()
+char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]);
+
+// Concatenate the strings 'strs' and do include-processing on the result. To free the return value, pass it to free()
+char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]);
+
+// Load the file 'filename' and do include-processing on the string therein. note that
+// 'filename' is opened directly; 'path_to_includes' is not used. To free the return value, pass it to free()
+char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]);
+
+#endif
+
+
+#ifdef STB_INCLUDE_IMPLEMENTATION
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *stb_include_load_file(char *filename, size_t *plen)
+{
+ char *text;
+ size_t len;
+ FILE *f = fopen(filename, "rb");
+ if (f == 0) return 0;
+ fseek(f, 0, SEEK_END);
+ len = (size_t) ftell(f);
+ if (plen) *plen = len;
+ text = (char *) malloc(len+1);
+ if (text == 0) return 0;
+ fseek(f, 0, SEEK_SET);
+ fread(text, 1, len, f);
+ fclose(f);
+ text[len] = 0;
+ return text;
+}
+
+typedef struct
+{
+ int offset;
+ int end;
+ char *filename;
+ int next_line_after;
+} include_info;
+
+static include_info *stb_include_append_include(include_info *array, int len, int offset, int end, char *filename, int next_line)
+{
+ include_info *z = (include_info *) realloc(array, sizeof(*z) * (len+1));
+ z[len].offset = offset;
+ z[len].end = end;
+ z[len].filename = filename;
+ z[len].next_line_after = next_line;
+ return z;
+}
+
+static void stb_include_free_includes(include_info *array, int len)
+{
+ int i;
+ for (i=0; i < len; ++i)
+ free(array[i].filename);
+ free(array);
+}
+
+static int stb_include_isspace(int ch)
+{
+ return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n');
+}
+
+// find location of all #include and #inject
+static int stb_include_find_includes(char *text, include_info **plist)
+{
+ int line_count = 1;
+ int inc_count = 0;
+ char *s = text, *start;
+ include_info *list = NULL;
+ while (*s) {
+ // parse is always at start of line when we reach here
+ start = s;
+ while (*s == ' ' || *s == '\t')
+ ++s;
+ if (*s == '#') {
+ ++s;
+ while (*s == ' ' || *s == '\t')
+ ++s;
+ if (0==strncmp(s, "include", 7) && stb_include_isspace(s[7])) {
+ s += 7;
+ while (*s == ' ' || *s == '\t')
+ ++s;
+ if (*s == '"') {
+ char *t = ++s;
+ while (*t != '"' && *t != '\n' && *t != '\r' && *t != 0)
+ ++t;
+ if (*t == '"') {
+ char *filename = (char *) malloc(t-s+1);
+ memcpy(filename, s, t-s);
+ filename[t-s] = 0;
+ s=t;
+ while (*s != '\r' && *s != '\n' && *s != 0)
+ ++s;
+ // s points to the newline, so s-start is everything except the newline
+ list = stb_include_append_include(list, inc_count++, start-text, s-text, filename, line_count+1);
+ }
+ }
+ } else if (0==strncmp(s, "inject", 6) && (stb_include_isspace(s[6]) || s[6]==0)) {
+ while (*s != '\r' && *s != '\n' && *s != 0)
+ ++s;
+ list = stb_include_append_include(list, inc_count++, start-text, s-text, NULL, line_count+1);
+ }
+ }
+ while (*s != '\r' && *s != '\n' && *s != 0)
+ ++s;
+ if (*s == '\r' || *s == '\n') {
+ s = s + (s[0] + s[1] == '\r' + '\n' ? 2 : 1);
+ }
+ ++line_count;
+ }
+ *plist = list;
+ return inc_count;
+}
+
+// avoid dependency on sprintf()
+static void stb_include_itoa(char str[9], int n)
+{
+ int i;
+ for (i=0; i < 8; ++i)
+ str[i] = ' ';
+ str[i] = 0;
+
+ for (i=1; i < 8; ++i) {
+ str[7-i] = '0' + (n % 10);
+ n /= 10;
+ if (n == 0)
+ break;
+ }
+}
+
+static char *stb_include_append(char *str, size_t *curlen, char *addstr, size_t addlen)
+{
+ str = (char *) realloc(str, *curlen + addlen);
+ memcpy(str + *curlen, addstr, addlen);
+ *curlen += addlen;
+ return str;
+}
+
+char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename, char error[256])
+{
+ char temp[4096];
+ include_info *inc_list;
+ int i, num = stb_include_find_includes(str, &inc_list);
+ size_t source_len = strlen(str);
+ char *text=0;
+ size_t textlen=0, last=0;
+ for (i=0; i < num; ++i) {
+ text = stb_include_append(text, &textlen, str+last, inc_list[i].offset - last);
+ // write out line directive for the include
+ #ifndef STB_INCLUDE_LINE_NONE
+ #ifdef STB_INCLUDE_LINE_GLSL
+ if (textlen != 0) // GLSL #version must appear first, so don't put a #line at the top
+ #endif
+ {
+ strcpy(temp, "#line ");
+ stb_include_itoa(temp+6, 1);
+ strcat(temp, " ");
+ #ifdef STB_INCLUDE_LINE_GLSL
+ stb_include_itoa(temp+15, i+1);
+ #else
+ strcat(temp, "\"");
+ if (inc_list[i].filename == 0)
+ strcmp(temp, "INJECT");
+ else
+ strcat(temp, inc_list[i].filename);
+ strcat(temp, "\"");
+ #endif
+ strcat(temp, "\n");
+ text = stb_include_append(text, &textlen, temp, strlen(temp));
+ }
+ #endif
+ if (inc_list[i].filename == 0) {
+ if (inject != 0)
+ text = stb_include_append(text, &textlen, inject, strlen(inject));
+ } else {
+ char *inc;
+ strcpy(temp, path_to_includes);
+ strcat(temp, "/");
+ strcat(temp, inc_list[i].filename);
+ inc = stb_include_file(temp, inject, path_to_includes, error);
+ if (inc == NULL) {
+ stb_include_free_includes(inc_list, num);
+ return NULL;
+ }
+ text = stb_include_append(text, &textlen, inc, strlen(inc));
+ free(inc);
+ }
+ // write out line directive
+ #ifndef STB_INCLUDE_LINE_NONE
+ strcpy(temp, "\n#line ");
+ stb_include_itoa(temp+6, inc_list[i].next_line_after);
+ strcat(temp, " ");
+ #ifdef STB_INCLUDE_LINE_GLSL
+ stb_include_itoa(temp+15, 0);
+ #else
+ strcat(temp, filename != 0 ? filename : "source-file");
+ #endif
+ text = stb_include_append(text, &textlen, temp, strlen(temp));
+ // no newlines, because we kept the #include newlines, which will get appended next
+ #endif
+ last = inc_list[i].end;
+ }
+ text = stb_include_append(text, &textlen, str+last, source_len - last + 1); // append '\0'
+ stb_include_free_includes(inc_list, num);
+ return text;
+}
+
+char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename, char error[256])
+{
+ char *text;
+ char *result;
+ int i;
+ size_t length=0;
+ for (i=0; i < count; ++i)
+ length += strlen(strs[i]);
+ text = (char *) malloc(length+1);
+ length = 0;
+ for (i=0; i < count; ++i) {
+ strcpy(text + length, strs[i]);
+ length += strlen(strs[i]);
+ }
+ result = stb_include_string(text, inject, path_to_includes, filename, error);
+ free(text);
+ return result;
+}
+
+char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256])
+{
+ size_t len;
+ char *result;
+ char *text = stb_include_load_file(filename, &len);
+ if (text == NULL) {
+ strcpy(error, "Error: couldn't load '");
+ strcat(error, filename);
+ strcat(error, "'");
+ return 0;
+ }
+ result = stb_include_string(text, inject, path_to_includes, filename, error);
+ free(text);
+ return result;
+}
+
+#if 0 // @TODO, GL_ARB_shader_language_include-style system that doesn't touch filesystem
+char *stb_include_preloaded(char *str, char *inject, char *includes[][2], char error[256])
+{
+
+}
+#endif
+
+#endif // STB_INCLUDE_IMPLEMENTATION
--- /dev/null
+#define STB_INCLUDE_IMPLEMENTATION
+#define STB_INCLUDE_LINE_GLSL
+#include "../dep/stb/stb_include.h"
+#define VG_TOOLS
+#include "vg/vg.h"
+
+struct uniform
+{
+ char name[30];
+ char type[20];
+}
+uniform_buffer[100];
+static int uniform_count;
+
+static int compile_subshader( FILE *header, char *name )
+{
+ char error[256];
+ char *full = stb_include_file( name, "", ".", error );
+
+ if( !full )
+ {
+ fprintf( stderr, "stb_include_file error:\n%s\n", error );
+ return 0;
+ }
+ else
+ {
+ /* VG */
+
+ fprintf( header, "{\n"
+ ".orig_file = \"../shaders/%s\",\n"
+ ".static_src = \n", name );
+
+ char *cur = full, *start = full;
+ while( 1 )
+ {
+ char c = *cur;
+ if( c == '\n' || c == '\0' )
+ {
+ *cur = '\0';
+ fputs( "\"", header );
+ fputs( start, header );
+
+ if( !strncmp(start,"uniform",7) )
+ {
+ start += 8;
+ struct uniform *uf = &uniform_buffer[ uniform_count ++ ];
+ for( int i=0;; i++ )
+ {
+ if( start[i] == '\0' )
+ break;
+
+ if( start[i] == ';' )
+ {
+ start[i] = '\0';
+ strncpy( uf->name, start, sizeof(uf->name) );
+ }
+
+ if( start[i] == ' ' )
+ {
+ start[i] = '\0';
+ strncpy( uf->type, start, sizeof(uf->type) );
+ start = start+i+1;
+ i=0;
+ }
+ }
+ }
+
+ if( c == '\0' )
+ {
+ fputs( "\"", header );
+ break;
+ }
+
+ fputs( "\\n\"\n", header );
+ start = cur+1;
+ }
+ cur ++;
+ }
+
+ fputs( "},", header );
+ }
+
+ free( full );
+ return 1;
+}
+
+int main( int argc, char *argv[] )
+{
+ if( argc < 2 || (argc-1)%3 != 0 )
+ {
+ fprintf( stderr, "invalid\n" );
+ return 0;
+ }
+
+ char path[260];
+ int shader_count = (argc-1)/3;
+ for( int i=0; i<shader_count; i++ )
+ {
+ char **args = &argv[1+i*3];
+ strcpy( path, args[0] );
+ strcat( path, ".h" );
+
+ printf( "Compiling shader called '%s'\n", args[0] );
+
+ FILE *header = fopen( path, "w" );
+ if( !header )
+ {
+ fprintf(stderr, "Could not open '%s'\n", path );
+ continue;
+ }
+
+ fprintf( header, "#ifndef SHADER_%s_H\n"
+ "#define SHADER_%s_H\n", args[0], args[0] );
+ fprintf( header, "static void shader_%s_link(void);\n", args[0] );
+ fprintf( header, "static void shader_%s_register(void);\n", args[0] );
+ fprintf( header, "static struct vg_shader _shader_%s = {\n"
+ " .name = \"%s\",\n"
+ " .link = shader_%s_link,\n"
+ " .vs = \n", args[0], args[0], args[0] );
+
+ uniform_count = 0;
+ if( !compile_subshader(header,args[1]) )
+ {
+ fclose( header );
+ continue;
+ }
+
+ fprintf( header, "\n .fs = \n" );
+ if( !compile_subshader(header,args[2]) )
+ {
+ fclose( header );
+ continue;
+ }
+
+ fprintf( header, "\n};\n\n" );
+
+ for( int i=0; i<uniform_count; i++ )
+ {
+ struct uniform *uf = &uniform_buffer[i];
+ fprintf( header, "static GLuint _uniform_%s_%s;\n", args[0], uf->name);
+ }
+
+ for( int i=0; i<uniform_count; i++ )
+ {
+ struct uniform *uf = &uniform_buffer[i];
+ if( !strcmp(uf->type,"vec2") )
+ {
+ fprintf( header, "static void shader_%s_%s(v2f v){\n"
+ " glUniform2fv( _uniform_%s_%s, 1, v );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"vec3") )
+ {
+ fprintf( header, "static void shader_%s_%s(v3f v){\n"
+ " glUniform3fv( _uniform_%s_%s, 1, v );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"vec4") )
+ {
+ fprintf( header, "static void shader_%s_%s(v4f v){\n"
+ " glUniform4fv( _uniform_%s_%s, 1, v );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"sampler2D") )
+ {
+ fprintf( header, "static void shader_%s_%s(int i){\n"
+ " glUniform1i( _uniform_%s_%s, i );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"float") )
+ {
+ fprintf( header, "static void shader_%s_%s(float f){\n"
+ " glUniform1f( _uniform_%s_%s, f );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"mat4x3") )
+ {
+ fprintf( header,
+ "static void shader_%s_%s(m4x3f m){\n"
+ " glUniformMatrix4x3fv"
+ "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"mat3") )
+ {
+ fprintf( header,
+ "static void shader_%s_%s(m3x3f m){\n"
+ " glUniformMatrix3fv"
+ "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ if( !strcmp(uf->type,"mat4") )
+ {
+ fprintf( header,
+ "static void shader_%s_%s(m4x4f m){\n"
+ " glUniformMatrix4fv"
+ "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n"
+ "}\n", args[0], uf->name, args[0], uf->name );
+ }
+ }
+
+ fprintf( header,
+ "static void shader_%s_register(void){\n"
+ " vg_shader_register( &_shader_%s );\n"
+ "}\n",
+ args[0],args[0] );
+
+ fprintf( header,
+ "static void shader_%s_use(void){ glUseProgram(_shader_%s.id); }\n",
+ args[0], args[0] );
+
+ fprintf( header,
+ "static void shader_%s_link(void){\n",
+ args[0] );
+
+ for( int i=0; i<uniform_count; i++ )
+ {
+ struct uniform *uf = &uniform_buffer[i];
+ fprintf( header,
+ " _uniform_%s_%s = "
+ "glGetUniformLocation( _shader_%s.id, \"%s\" );\n",
+ args[0], uf->name,
+ args[0], uf->name );
+ }
+
+ fprintf( header, "}\n" );
+ fprintf( header, "#endif /* SHADER_%s_H */\n", args[0] );
+ fclose( header );
+ }
+}
vg_register();
vg_register_exit( &vg_free, "vg_free" );
+
+
+ vg_shaders_recompile(0,NULL);
+ vg_register_exit( &vg_shaders_free, "vg_shaders_free" );
+ vg_function_push( (struct vg_cmd){
+ .name = "shaders",
+ .function = vg_shaders_recompile
+ });
+
- if( vg_shaders_compile() )
- {
- vg_start();
+ vg_start();
+
+ vg_console_init();
+ vg_register_exit( &vg_console_free, "Console" );
+
+ vg_audio_init();
+ vg_register_exit( &vg_audio_free, "vg_audio_free" );
- vg_console_init();
- vg_register_exit( &vg_console_free, "Console" );
+ vg_debugtools_setup();
- vg_audio_init();
- vg_register_exit( &vg_audio_free, "vg_audio_free" );
+ /*
+ * Main gameloop
+ */
+ while( !glfwWindowShouldClose( vg_window ) )
+ {
+ v2_copy( (v2f){ 0.0f, 0.0f }, vg_mouse_wheel );
+
+ glfwPollEvents();
- vg_debugtools_setup();
+ #ifdef VG_STEAM
+ sw_event_loop();
+ #endif
+
+ vg_time_last = vg_time;
+ vg_time = glfwGetTime();
+ vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f );
+
+ vg_update_inputs();
+ vg_update();
+ vg_render();
+
+ vg_lines_drawall((float*)vg_pv);
- /*
- * Main gameloop
- */
- while( !glfwWindowShouldClose( vg_window ) )
{
- v2_copy( (v2f){ 0.0f, 0.0f }, vg_mouse_wheel );
-
- glfwPollEvents();
-
- #ifdef VG_STEAM
- sw_event_loop();
- #endif
+ ui_begin( &ui_global_ctx, vg_window_x, vg_window_y );
+ ui_set_mouse( &ui_global_ctx, vg_mouse[0], vg_mouse[1],
+ vg_get_button_state( "primary" ) );
- vg_time_last = vg_time;
- vg_time = glfwGetTime();
- vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f );
+ vg_ui();
+ vg_console_draw();
+ vg_debugtools_draw();
- vg_update_inputs();
- vg_update();
- vg_render();
-
- vg_lines_drawall((float*)vg_pv);
-
- {
- ui_begin( &ui_global_ctx, vg_window_x, vg_window_y );
- ui_set_mouse( &ui_global_ctx, vg_mouse[0], vg_mouse[1],
- vg_get_button_state( "primary" ) );
-
- vg_ui();
- vg_console_draw();
- vg_debugtools_draw();
-
- ui_resolve( &ui_global_ctx );
- ui_draw( &ui_global_ctx, NULL );
- }
-
- glfwSwapBuffers( vg_window );
- VG_CHECK_GL();
+ ui_resolve( &ui_global_ctx );
+ ui_draw( &ui_global_ctx, NULL );
}
+
+ glfwSwapBuffers( vg_window );
+ VG_CHECK_GL();
}
vg_exit();
/* Modifiers */
sfx_vol_control *vol_src;
- float vol, cvol;
+ float vol, cvol, pan;
+
+ u32 delay;
/* Info */
u32 ch, end, cur;
return val;
}
-void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput, ma_uint32 frameCount );
+void audio_mixer_callback( ma_device *pDevice, void *pOutBuf,
+ const void *pInput, ma_uint32 frameCount );
static void vg_audio_init(void)
{
if( sys->flags & SFX_FLAG_PERSISTENT )
{
sys->vol = sys->persisitent_source->vol * g_master_volume;
+ sys->pan = sys->persisitent_source->pan;
/* Fadeout effect ( + remove ) */
if( sys->persisitent_source->fadeout )
samples_this_run = VG_MIN( samples_this_run, sys->fadeout_current );
}
- for( u32 j = 0; j < samples_this_run; j ++ )
+ for( u32 j=0; j<samples_this_run; j++ )
{
audio_mixer_getsamples( pcf, sys->source, cursor, sys->ch );
break;
}
- pOut32F[ buffer_pos*2+0 ] += pcf[0] * vol;
- pOut32F[ buffer_pos*2+1 ] += pcf[1] * vol;
+ float sl = 1.0f-sys->pan,
+ sr = 1.0f+sys->pan;
+
+ pOut32F[ buffer_pos*2+0 ] += pcf[0] * vol * sl;
+ pOut32F[ buffer_pos*2+1 ] += pcf[1] * vol * sr;
cursor ++;
buffer_pos ++;
{
if( frames_write )
{
- cursor = 0;
+ cursor = sys->clip_start;
continue;
}
}
/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
+#ifndef VG_INPUT_H
+#define VG_INPUT_H
static inline float vg_get_axis( const char *axis );
static inline int vg_get_button( const char *button );
{
const char *name;
int bind;
- int controller;
int value; int prev;
}
-vg_button_binds[];
+vg_button_binds[],
+vg_controller_binds[];
#include "vg_config.h"
static inline float vg_get_axis( const char *axis )
{
for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
- {
if( !strcmp( axis, vg_axis_binds[i].name ) )
- {
return vg_axis_binds[i].value;
- }
- }
}
static inline struct button_binding *vg_get_button_ptr( const char *button )
{
for( int i=0; i<vg_list_size(vg_button_binds); i ++ )
- {
if( !strcmp(button,vg_button_binds[i].name) )
- {
return vg_button_binds + i;
- }
- }
+ return NULL;
+}
+
+static inline struct button_binding *vg_get_button_ptr_c( const char *button )
+{
+ for( int i=0; i<vg_list_size(vg_controller_binds); i ++ )
+ if( !strcmp(button,vg_controller_binds[i].name) )
+ return vg_controller_binds + i;
+ return NULL;
}
+
#pragma GCC diagnostic pop
static int vg_console_enabled(void);
+static inline void vg_get_button_states( const char *name, int *cur, int *prev )
+{
+ struct button_binding *bind = vg_get_button_ptr( name ),
+ *bindc = vg_get_button_ptr_c( name );
+
+ *cur = 0; *prev = 0;
+
+ if( bind )
+ {
+ *cur |= bind->value;
+ *prev |= bind->prev;
+ }
+
+ if( bindc )
+ {
+ *cur |= bindc->value;
+ *prev |= bindc->prev;
+ }
+}
+
static inline int vg_get_button( const char *button )
{
- return vg_get_button_ptr( button )->value && !vg_console_enabled();
+ int cur, prev;
+ vg_get_button_states( button, &cur, &prev );
+
+ return cur && !vg_console_enabled();
}
static inline int vg_get_button_down( const char *button )
{
- struct button_binding *bind = vg_get_button_ptr( button );
- return bind->value & (bind->value ^ bind->prev) && !vg_console_enabled();
+ int cur, prev;
+ vg_get_button_states( button, &cur, &prev );
+
+ return cur & (cur ^ prev) && !vg_console_enabled();
}
static inline int vg_get_button_up( const char *button )
{
- struct button_binding *bind = vg_get_button_ptr( button );
- return bind->prev & (bind->value ^ bind->prev) && !vg_console_enabled();
+ int cur, prev;
+ vg_get_button_states( button, &cur, &prev );
+
+ return prev & (cur ^ prev) && !vg_console_enabled();
}
static inline enum vg_button_state vg_get_button_state( const char *button )
{
struct button_binding *binding = vg_button_binds + i;
binding->prev = binding->value;
-
- if( binding->controller )
- binding->value = vg_gamepad.buttons[ binding->controller ];
- else
- binding->value = get_button_cross_device( binding->bind );
+ binding->value = get_button_cross_device( binding->bind );
}
+
+ for( int i=0; i<vg_list_size( vg_controller_binds ); i++ )
+ {
+ struct button_binding *binding = vg_controller_binds + i;
+ binding->prev = binding->value;
+ binding->value = vg_gamepad.buttons[ binding->bind ];
+ }
/* Update axis inputs */
for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ )
}
}
}
+
+#endif
typedef v2f line_co;
#endif
-SHADER_DEFINE( vg_line_shader,
+static struct vg_shader _shader_lines =
+{
+ .name = "[vg] lines",
+ .link = NULL,
+ .vs =
+ {
+ .orig_file = NULL,
+ .static_src =
+
#ifdef VG_3D
"uniform mat4 uPv;"
"layout (location=0) in vec3 a_co;"
#endif
" s_colour = a_colour;"
" gl_Position = vert_pos;"
- "}",
-
- // FRAGMENT
+ "}"
+ },
+ .fs =
+ {
+ .orig_file = NULL,
+ .static_src =
+
"out vec4 FragColor;"
""
"in vec4 s_colour;"
"{"
" FragColor = s_colour;"
"}"
- ,
- UNIFORMS({ "uPv" })
-)
+ }
+};
struct
{
.opt_i32 = { .min=0, .max=1, .clamp=1 },
.persistent = 1
});
-
- SHADER_INIT( vg_line_shader );
+
+ vg_shader_register( &_shader_lines );
glGenVertexArrays( 1, &vg_lines.vao );
glGenBuffers( 1, &vg_lines.vbo );
static void vg_lines_drawall( float* projection )
{
- SHADER_USE( vg_line_shader );
+ glUseProgram( _shader_lines.id );
#ifdef VG_3D
glUniformMatrix4fv
#else
glUniformMatrix3fv
#endif
- ( SHADER_UNIFORM( vg_line_shader, "uPv" ), 1, GL_FALSE, projection );
+ ( glGetUniformLocation( _shader_lines.id, "uPv" ), 1, GL_FALSE, projection );
glBindVertexArray( vg_lines.vao );
glBindBuffer( GL_ARRAY_BUFFER, vg_lines.vbo );
vg_line( p111, p011, colour );
}
+static void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour )
+{
+ v3f p000, p001, p010, p011, p100, p101, p110, p111;
+
+ p000[0]=box[0][0];p000[1]=box[0][1];p000[2]=box[0][2];
+ p001[0]=box[0][0];p001[1]=box[0][1];p001[2]=box[1][2];
+ p010[0]=box[0][0];p010[1]=box[1][1];p010[2]=box[0][2];
+ p011[0]=box[0][0];p011[1]=box[1][1];p011[2]=box[1][2];
+
+ p100[0]=box[1][0];p100[1]=box[0][1];p100[2]=box[0][2];
+ p101[0]=box[1][0];p101[1]=box[0][1];p101[2]=box[1][2];
+ p110[0]=box[1][0];p110[1]=box[1][1];p110[2]=box[0][2];
+ p111[0]=box[1][0];p111[1]=box[1][1];p111[2]=box[1][2];
+
+ m4x3_mulv( m, p000, p000 );
+ m4x3_mulv( m, p001, p001 );
+ m4x3_mulv( m, p010, p010 );
+ m4x3_mulv( m, p011, p011 );
+ m4x3_mulv( m, p100, p100 );
+ m4x3_mulv( m, p101, p101 );
+ m4x3_mulv( m, p110, p110 );
+ m4x3_mulv( m, p111, p111 );
+
+ vg_line( p000, p001, colour );
+ vg_line( p001, p011, colour );
+ vg_line( p011, p010, colour );
+ vg_line( p010, p000, colour );
+
+ vg_line( p100, p101, colour );
+ vg_line( p101, p111, colour );
+ vg_line( p111, p110, colour );
+ vg_line( p110, p100, colour );
+
+ vg_line( p100, p000, colour );
+ vg_line( p101, p001, colour );
+ vg_line( p110, p010, colour );
+ vg_line( p111, p011, colour );
+
+ vg_line( p000, p110, colour );
+ vg_line( p100, p010, colour );
+}
+
static void vg_line_pt3( v3f pt, float size, u32 colour )
{
boxf box =
return (float)rand()/(float)(RAND_MAX);
}
-static inline float vg_randint(int max)
+static inline int vg_randint(int max)
{
return rand()%max;
}
+static float stable_force( float current, float diff )
+{
+ float fnew = current + diff;
+
+ if( fnew * current < 0.0f )
+ return 0.0f;
+
+ return fnew;
+}
+
#define VG_MIN( A, B ) ((A)<(B)?(A):(B))
#define VG_MAX( A, B ) ((A)>(B)?(A):(B))
v2_muls( a, 1.f / v2_length( a ), a );
}
+static inline void v2_floor( v2f a, v2f b )
+{
+ b[0] = floorf( a[0] );
+ b[1] = floorf( a[1] );
+}
+
/*
* Vector 3
*/
a[0] = 0.f; a[1] = 0.f; a[2] = 0.f; a[3] = 0.f;
}
-static inline void v4_muladds( v3f a, v3f b, float s, v3f d )
+static inline void v4_muls( v4f a, float s, v4f d )
+{
+ d[0] = a[0]*s;
+ d[1] = a[1]*s;
+ d[2] = a[2]*s;
+ d[3] = a[3]*s;
+}
+
+static inline void v4_muladds( v4f a, v4f b, float s, v4f d )
{
d[0] = a[0]+b[0]*s;
d[1] = a[1]+b[1]*s;
v3_copy( res, d );
}
+/*
+ * Transform plane ( xyz, distance )
+ */
+static inline void m4x3_mulp( m4x3f m, v4f p, v4f d )
+{
+ v3f o;
+
+ v3_muls( p, p[3], o );
+ m4x3_mulv( m, o, o );
+ m3x3_mulv( m, p, d );
+
+ d[3] = v3_dot( o, d );
+}
+
/*
* Affine transforms
*/
v3_muls( m[2], s, m[2] );
}
+static inline void m4x3_scalev( m4x3f m, v3f v )
+{
+ v3_muls(m[0], v[0], m[0]);
+ v3_muls(m[1], v[1], m[1]);
+ v3_muls(m[2], v[2], m[2]);
+}
+
static inline void m4x3_rotate_x( m4x3f m, float angle )
{
m4x3f t = M4X3_IDENTITY;
v3_copy( a[1], b[1] );
}
+static inline int box_overlap( boxf a, boxf b )
+{
+ return
+ ( a[0][0] <= b[1][0] && a[1][0] >= b[0][0] ) &&
+ ( a[0][1] <= b[1][1] && a[1][1] >= b[0][1] ) &&
+ ( a[0][2] <= b[1][2] && a[1][2] >= b[0][2] )
+ ;
+}
+
static inline void box_init_inf( boxf box )
{
v3_fill( box[0], INFINITY );
v3_fill( box[0], INFINITY );
v3_fill( box[1], -INFINITY );
- m4x3_expand_aabb_point( m, box, a );
+ m4x3_expand_aabb_point( m, box, (v3f){ a[0], a[1], a[2] } );
m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], a[2] } );
- m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], a[2] } );
m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], a[2] } );
- m4x3_expand_aabb_point( m, box, b );
+ m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], a[2] } );
+
+ m4x3_expand_aabb_point( m, box, (v3f){ a[0], a[1], b[2] } );
m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], b[2] } );
- m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], b[2] } );
m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], b[2] } );
+ m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], b[2] } );
+}
+
+int ray_aabb( boxf box, v3f co, v3f dir, float dist )
+{
+ v3f v0, v1;
+ float tmin, tmax;
+
+ v3_sub( box[0], co, v0 );
+ v3_sub( box[1], co, v1 );
+ v3_div( v0, dir, v0 );
+ v3_div( v1, dir, v1 );
+
+ tmin = vg_minf( v0[0], v1[0] );
+ tmax = vg_maxf( v0[0], v1[0] );
+ tmin = vg_maxf( tmin, vg_minf( v0[1], v1[1] ));
+ tmax = vg_minf( tmax, vg_maxf( v0[1], v1[1] ));
+ tmin = vg_maxf( tmin, vg_minf( v0[2], v1[2] ));
+ tmax = vg_minf( tmax, vg_maxf( v0[2], v1[2] ));
+
+ return tmax >= tmin && tmin < dist && tmax > 0;
}
static inline void m4x3_lookat( m4x3f m, v3f pos, v3f target, v3f up )
{ 0.0f, 1.0f, 0.0f, 0.0f },\
{ 0.0f, 0.0f, 1.0f, 0.0f },\
{ 0.0f, 0.0f, 0.0f, 1.0f }}
+#define M4X4_ZERO {{0.0f, 0.0f, 0.0f, 0.0f },\
+ { 0.0f, 0.0f, 0.0f, 0.0f },\
+ { 0.0f, 0.0f, 0.0f, 0.0f },\
+ { 0.0f, 0.0f, 0.0f, 0.0f }}
static void m4x4_projection( m4x4f m, float angle,
float ratio, float near, float far )
m4x4_copy( id, a );
}
+static inline void m4x4_zero( m4x4f a )
+{
+ m4x4f zero = M4X4_ZERO;
+ m4x4_copy( zero, a );
+}
+
static inline void m4x4_mul( m4x4f a, m4x4f b, m4x4f d )
{
float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3],
d[3][3] = a03*b30 + a13*b31 + a23*b32 + a33*b33;
}
+static inline void m4x4_mulv( m4x4f m, v4f v, v4f d )
+{
+ v4f res;
+
+ res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3];
+ res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3];
+ res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3];
+ res[3] = m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3];
+
+ v4_copy( res, d );
+}
+
+static inline void m4x4_inv( m4x4f a, m4x4f d )
+{
+ float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3],
+ a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3],
+ a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3],
+ a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3],
+ det,
+ t[6];
+
+ t[0] = a22*a33 - a32*a23;
+ t[1] = a21*a33 - a31*a23;
+ t[2] = a21*a32 - a31*a22;
+ t[3] = a20*a33 - a30*a23;
+ t[4] = a20*a32 - a30*a22;
+ t[5] = a20*a31 - a30*a21;
+
+ d[0][0] = a11*t[0] - a12*t[1] + a13*t[2];
+ d[1][0] =-(a10*t[0] - a12*t[3] + a13*t[4]);
+ d[2][0] = a10*t[1] - a11*t[3] + a13*t[5];
+ d[3][0] =-(a10*t[2] - a11*t[4] + a12*t[5]);
+
+ d[0][1] =-(a01*t[0] - a02*t[1] + a03*t[2]);
+ d[1][1] = a00*t[0] - a02*t[3] + a03*t[4];
+ d[2][1] =-(a00*t[1] - a01*t[3] + a03*t[5]);
+ d[3][1] = a00*t[2] - a01*t[4] + a02*t[5];
+
+ t[0] = a12*a33 - a32*a13;
+ t[1] = a11*a33 - a31*a13;
+ t[2] = a11*a32 - a31*a12;
+ t[3] = a10*a33 - a30*a13;
+ t[4] = a10*a32 - a30*a12;
+ t[5] = a10*a31 - a30*a11;
+
+ d[0][2] = a01*t[0] - a02*t[1] + a03*t[2];
+ d[1][2] =-(a00*t[0] - a02*t[3] + a03*t[4]);
+ d[2][2] = a00*t[1] - a01*t[3] + a03*t[5];
+ d[3][2] =-(a00*t[2] - a01*t[4] + a02*t[5]);
+
+ t[0] = a12*a23 - a22*a13;
+ t[1] = a11*a23 - a21*a13;
+ t[2] = a11*a22 - a21*a12;
+ t[3] = a10*a23 - a20*a13;
+ t[4] = a10*a22 - a20*a12;
+ t[5] = a10*a21 - a20*a11;
+
+ d[0][3] =-(a01*t[0] - a02*t[1] + a03*t[2]);
+ d[1][3] = a00*t[0] - a02*t[3] + a03*t[4];
+ d[2][3] =-(a00*t[1] - a01*t[3] + a03*t[5]);
+ d[3][3] = a00*t[2] - a01*t[4] + a02*t[5];
+
+ det = 1.0f / (a00*d[0][0] + a01*d[1][0] + a02*d[2][0] + a03*d[3][0]);
+ v4_muls( d[0], det, d[0] );
+ v4_muls( d[1], det, d[1] );
+ v4_muls( d[2], det, d[2] );
+ v4_muls( d[3], det, d[3] );
+}
+
/*
* Planes (double precision)
*/
q[3] = rinv * (m[0][1] - m[1][0]);
}
}
+
+static int ray_tri( v3f tri[3], v3f co, v3f dir, float *dist )
+{
+ float const kEpsilon = 0.00001f;
+
+ v3f v0, v1, h, s, q, n;
+ float a,f,u,v,t;
+
+ float *pa = tri[0],
+ *pb = tri[1],
+ *pc = tri[2];
+
+ v3_sub( pb, pa, v0 );
+ v3_sub( pc, pa, v1 );
+ v3_cross( dir, v1, h );
+ v3_cross( v0, v1, n );
+
+ if( v3_dot( n, dir ) > 0.0f ) /* Backface culling */
+ return 0;
+
+ /* Parralel */
+ a = v3_dot( v0, h );
+ if( a > -kEpsilon && a < kEpsilon )
+ return 0;
+
+ f = 1.0f/a;
+ v3_sub( co, pa, s );
+
+ u = f * v3_dot(s, h);
+ if( u < 0.0f || u > 1.0f )
+ return 0;
+
+ v3_cross( s, v0, q );
+ v = f * v3_dot( dir, q );
+ if( v < 0.0f || u+v > 1.0f )
+ return 0;
+
+ t = f * v3_dot(v1, q);
+ if( t > kEpsilon )
+ {
+ *dist = t;
+ return 1;
+ }
+ else return 0;
+}
-/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
+/* TODO: TUrn off in release */
+#define STB_INCLUDE_IMPLEMENTATION
+#define STB_INCLUDE_LINE_GLSL
+#include "stb/stb_include.h"
const char *vg_shader_gl_ver = "#version 330 core\n";
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wreturn-type"
-static inline int static_str_index( const char *list[], int len,
- const char *str )
-{
- for( int i = 0; i < len; i ++ )
- {
- if( !strcmp(list[i],str) )
- return i;
- }
-
- #ifndef VG_RELEASE
- fprintf( stderr, "That was not a static string index!! (%s)\n", str );
- abort();
- #endif
-}
-#pragma GCC diagnostic pop
-
-#define SHADER_NAME( NAME ) (NAME##_static_shader.program)
-#define SHADER_USE( NAME ) glUseProgram( NAME##_static_shader.program )
-
-#define SHADER_UNIFORM( NAME, U ) \
- NAME##_shader_uniforms[ STR_STATIC_INDEX( NAME##_shader_names, U ) ]
-#define SHADER_UNIFORM_NAME( NAME, UID ) NAME##_shader_names[ UID ]
-#define STR_STATIC_INDEX( LIST, STR ) \
- static_str_index( LIST, vg_list_size(LIST), STR )
-
-#define UNIFORMS(...) __VA_ARGS__
-
-#define SHADER_DEFINE( NAME, VERT, FRAG, UNIFORMS ) \
- const char * NAME##_shader_names[] = UNIFORMS; \
- GLint NAME##_shader_uniforms[ vg_list_size( NAME##_shader_names ) ]; \
- struct vg_shader NAME##_static_shader = { \
- .src_vert = VERT, .src_frag = FRAG, \
- .sym = #NAME "_static.shader", \
- .uniform_names = NAME##_shader_names, \
- .uniforms = NAME##_shader_uniforms, \
- .uniform_count = vg_list_size( NAME##_shader_names ), \
- };
-
-#define SHADER_INIT( NAME ) arrpush( vg_shaders_active, &NAME##_static_shader )
-
-#define SHADER_STATUS_NONE 0x00
-#define SHADER_STATUS_COMPILED 0x1
-
struct vg_shader
{
- GLuint program;
+ GLuint id;
+ const char *name;
- const char *src_vert;
- const char *src_frag;
- const char *src_geo;
- const char *sym;
-
- const char **uniform_names;
- GLint *uniforms;
- u32 uniform_count;
- u32 status;
+ struct vg_subshader
+ {
+ const char *orig_file,
+ *static_src;
+ }
+ vs, fs;
+
+ void (*link)(void);
+ int compiled;
}
** vg_shaders_active = NULL;
return 0;
}
- glShaderSource( shader, 2, (const char *[2]){ vg_shader_gl_ver, src }, NULL );
+ glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL );
glCompileShader( shader );
GLint status;
static int vg_shader_compile( struct vg_shader *shader )
{
- vg_info( "Compile shader '%s'\n", shader->sym );
+ vg_info( "Compile shader '%s'\n", shader->name );
- GLuint vert, frag, geo = 0;
+ GLuint program, vert, frag;
+ const char *svs, *sfs;
+ char *avs, *afs;
+
+ int static_src = 1;
+
+ /* If we are compiling this again, we obviously need to try to take the src
+ * from the disk instead.
+ *
+ * Only do this if we have filenames set on the shader, so engine shaders
+ * dont have to do it (text.. etc).
+ */
+ if( shader->compiled )
+ {
+ if( shader->vs.orig_file && shader->fs.orig_file )
+ static_src = 0;
+ else return 1;
+ }
+
+ if( static_src )
+ {
+ svs = shader->vs.static_src;
+ sfs = shader->fs.static_src;
+ }
+ else
+ {
+ char error[260];
+ char path[260];
+ strcpy( path, shader->vs.orig_file );
+ avs = stb_include_file( path, "", "../shaders", error );
+
+ strcpy( path, shader->fs.orig_file );
+ afs = stb_include_file( path, "", "../shaders", error );
+
+ if( !avs || !afs )
+ {
+ free( avs );
+ free( afs );
+ return 0;
+ }
+
+ svs = avs;
+ sfs = afs;
+ }
- vert = vg_shader_subshader( shader->src_vert, GL_VERTEX_SHADER );
- frag = vg_shader_subshader( shader->src_frag, GL_FRAGMENT_SHADER );
+ vert = vg_shader_subshader( svs, GL_VERTEX_SHADER );
+ frag = vg_shader_subshader( sfs, GL_FRAGMENT_SHADER );
+ if( !static_src )
+ {
+ free( avs );
+ free( afs );
+ }
+
if( !vert || !frag )
return 0;
- if( shader->src_geo )
- {
- geo = vg_shader_subshader( shader->src_geo, GL_GEOMETRY_SHADER );
-
- if( !geo )
- return 0;
- }
-
- shader->program = glCreateProgram();
- if( geo )
- glAttachShader( shader->program, geo );
+ program = glCreateProgram();
- glAttachShader( shader->program, vert );
- glAttachShader( shader->program, frag );
- glLinkProgram( shader->program );
+ glAttachShader( program, vert );
+ glAttachShader( program, frag );
+ glLinkProgram( program );
glDeleteShader( vert );
glDeleteShader( frag );
-
- if( geo )
- glDeleteShader( geo );
/* Check for link errors */
char infoLog[ 512 ];
int success_link = 1;
- glGetProgramiv( shader->program, GL_LINK_STATUS, &success_link );
+ glGetProgramiv( program, GL_LINK_STATUS, &success_link );
if( !success_link )
{
- glGetProgramInfoLog( shader->program, 512, NULL, infoLog );
+ glGetProgramInfoLog( program, 512, NULL, infoLog );
vg_error( "Link failed: %s\n", infoLog );
- glDeleteProgram( shader->program );
-
+ glDeleteProgram( program );
return 0;
}
- /* Complete linkeage */
- for( int i = 0; i < shader->uniform_count; i ++ )
- {
- shader->uniforms[ i ] =
- glGetUniformLocation( shader->program, shader->uniform_names[i] );
- }
-
- shader->status |= SHADER_STATUS_COMPILED;
+ if( shader->compiled )
+ glDeleteProgram( shader->id );
+
+ shader->id = program;
+ shader->compiled = 1;
+ if( shader->link )
+ shader->link();
return 1;
}
{
struct vg_shader *shader = vg_shaders_active[i];
- if( shader->status & SHADER_STATUS_COMPILED )
- glDeleteProgram( shader->program );
+ if( shader->compiled )
+ glDeleteProgram( shader->id );
}
arrfree( vg_shaders_active );
}
-static int vg_shaders_compile(void)
+static int vg_shaders_recompile(int argc, const char *argv[])
{
vg_info( "Compiling shaders\n" );
-
for( int i = 0; i < arrlen( vg_shaders_active ); i ++ )
{
struct vg_shader *shader = vg_shaders_active[i];
- if( !vg_shader_compile( shader ) )
- {
- vg_shaders_free();
- return 0;
- }
+ vg_shader_compile( shader );
}
-
- vg_register_exit( &vg_shaders_free, "vg_shaders_free" );
- return 1;
+
+ return 0;
+}
+
+static void vg_shader_register( struct vg_shader *shader )
+{
+ shader->compiled = 0;
+ shader->id = 0; /* TODO: make this an error shader */
+ arrpush( vg_shaders_active, shader );
}
--- /dev/null
+struct vg_subshader
+{
+ const char *static_src,
+ *orig_file;
+
+ void (*uniform_register)(void);
+};
+
+struct vg_shader
+{
+ struct vg_subshader vs, fs;
+};
+
#ifndef VG_UI_H
#define VG_UI_H
-SHADER_DEFINE( shader_ui,
-
+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;"
"aWsp = a_co;"
"aClip = a_clip;"
"}",
-
- /* Fragment */
+ },
+ .fs =
+ {
+ .orig_file = NULL,
+ .static_src =
"uniform sampler2D uTexGlyphs;"
"out vec4 FragColor;"
""
"FragColor = vec4( aColour.rgb, glyph.a*clip_blend );"
"}"
- ,
- UNIFORMS({ "uPv", "uTexGlyphs" })
-)
+ }
+};
typedef i16 ui_px;
typedef u32 ui_colour;
free( image );
- SHADER_INIT( shader_ui );
+ vg_shader_register( &_shader_ui );
ui_init_context( &ui_global_ctx, 20000 );
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
- SHADER_USE( shader_ui );
+ glUseProgram( _shader_ui.id );
m3x3f view = M3X3_IDENTITY;
-1.0f/((float)vg_window_y*0.5f), 1.0f } );
}
- glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1,
+ /* TODO? */
+ glUniformMatrix3fv( glGetUniformLocation( _shader_ui.id, "uPv" ), 1,
GL_FALSE, (float *)view_override );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, ui_glyph_texture );
- glUniform1i( SHADER_UNIFORM( shader_ui, "uTexGlyphs" ), 0 );
+ glUniform1i( glGetUniformLocation( _shader_ui.id, "uTexGlyphs" ), 0 );
glDrawElements( GL_TRIANGLES, num_indices_normal,
GL_UNSIGNED_SHORT, (void*)(0) );
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;
+};
+
+static void ui_slider( ui_ctx *ctx, struct ui_slider *slider )
+{
+ ui_new_node( ctx );
+
+ ui_px slider_start = ctx->cursor[0];
+
+ float const ftotal = ctx->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( ctx, ctx->cursor, 0xff111111 );
+ ctx->cursor[2] = fwidth;
+ ctx->cursor[0] = slider_start + fpos * fmove;
+
+ /* TODO.. */
+ u32 uid = (u32)(u64)slider->data;
+ int status = ui_button( ctx, uid );
+
+ if( ctx->capture_lock &&
+ (ctx->capture_mouse_id == ui_group_id( ctx, uid )))
+ {
+ float ui_new = ctx->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 );
+ }
+
+ ctx->cursor[0] += 4;
+ ctx->cursor[1] += 4;
+
+ char buf[12];
+ snprintf( buf, 12, "%.2f", *slider->data );
+ ui_text( ctx, ctx->cursor, buf, 1, 0 );
+ ui_end_down( ctx );
+
+ ui_end_down( ctx );
+}
+
+static void ui_slider_vector( ui_ctx *ctx, 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( ctx, &slider->sub[i] );
+ }
+}
+
+static void ui_checkbox( ui_ctx *ctx, struct ui_checkbox *cb )
+{
+ u32 uid = (u32)(u64)cb->data;
+ if( ui_button(ctx,uid) == k_button_click )
+ *cb->data ^= 0x1;
+
+ ui_new_node(ctx);
+ ui_rect_pad( ctx->cursor, 4 );
+ if( *cb->data )
+ ui_fill_rect( ctx, ctx->cursor, 0xff00e052 );
+ else
+ ui_fill_rect( ctx, ctx->cursor, 0xff0052e0 );
+
+ ui_end(ctx);
+ ui_end_down(ctx);
+}
+
/* Shortnames */
#define gui_draw(...) ui_draw( &ui_global_ctx, __VA_ARGS__)
#define gui_current(...) ui_current( &ui_global_ctx, __VA_ARGS__)
vg_version="0.2"
opt_assets=false
+opt_shaders=false
opt_release=false
opt_play=false
opt_linux=false
target_platform_include=""
target_standard="-std=c99"
target_link_steam=false
+target_shaders=""
# Util
# ===========================================
target_os_linux(){
target_ext=""
- target_compiler="clang"
+ target_compiler="gcc"
target_libs="-lGL -lglfw3 -lX11 -lXxf86vm -lXrandr -lm -pthread -lXi -ldl"
target_libs_steam="-lsteam_api"
#target_platform_include="-include $vg_root/platformutils/force_link_glibc_2.23.h"
if [ "$opt_steam" != "" ]; then
cp $vg_root/dep/steam/$target_steam_api $target_dir/$target_steam_api
fi
-
- # Clear and copy assets
- rm -r $target_dir/textures
- rm -r $target_dir/sound
- rm -r $target_dir/maps
-
- cp -r .temp_textures $target_dir
- mv $target_dir/.temp_textures $target_dir/textures
- cp -r sound $target_dir
- cp -r maps $target_dir
- cp -r models $target_dir
}
compile_tools(){
compile_x $vg_root/src/fontcomp.c $vg_root/bin/fontcomp
compile_x $vg_root/src/texsheet.c $vg_root/bin/texsheet
compile_x $vg_root/src/qoiconv.c $vg_root/bin/qoiconv
+ compile_x $vg_root/src/shader.c $vg_root/bin/shader
opt_steam=$steam_prev
}
-
compile_assets(){
titleit "Assets"
[[ -d .temp_textures ]] && rm -r .temp_textures
done
if [[ -d "textures_combine" ]]; then
- # Autocombine textures
echo " [combine]:"
auto_combine=""
do logit " combine: $f";
auto_combine="$auto_combine $f"
done
- $vg_root/bin/texsheet$taget_ext ../.temp_textures/autocombine.qoi ../sprites_autocombine.h sprites_auto_combine $auto_combine
+ $vg_root/bin/texsheet$target_ext ../.temp_textures/autocombine.qoi ../sprites_autocombine.h sprites_auto_combine $auto_combine
cd ..
fi
echo ""
echo "Compile fonts:"
$vg_root/bin/fontcomp$target_ext $vg_root/src/fonts/vg_font.png $vg_root/src/vg/vg_pxfont.h
+
+ # Clear and copy assets
+ rm -r $target_dir/textures
+ rm -r $target_dir/sound
+ rm -r $target_dir/maps
+
+ cp -r .temp_textures $target_dir
+ mv $target_dir/.temp_textures $target_dir/textures
+ cp -r sound $target_dir
+ cp -r maps $target_dir
+ cp -r models $target_dir
+}
+
+compile_shaders(){
+ titleit "Shaders"
+
+ if [[ -d "shaders" ]]; then
+ cd shaders
+ $vg_root/bin/shader$target_ext $target_shaders
+ cd ..
+ fi
+}
+
+shader(){
+ target_shaders="$target_shaders $1 $2 $3"
}
# ==============================================================
# Compile process
-options=rptlwa
+options=rptlwas
longopts=release,build-linux,build-windows,steam,play,build-tools,assets,full,miniaudio,template
parsed=$(getopt --options=$options --longoptions=$longopts --name "vgc" -- "$@")
eval set -- "$parsed"
while true; do
case "$1" in
+ -s|--shaders)
+ opt_shaders=true
+ shift;
+ ;;
-a|--assets)
opt_assets=true
+ opt_shaders=true
shift;
;;
-r|--release)
titleit " vgc ver: $vg_version\n host: $host_os"
logit " assets: $opt_assets"
+logit " shaders: $opt_shaders"
logit " release: $opt_release"
logit " play: $opt_play"
logit " build-linux: $opt_linux"
if [ $opt_tools = true ]; then detect_os; compile_tools; fi
if [ $opt_assets = true ]; then compile_assets; fi
+if [ $opt_shaders = true ]; then compile_shaders; fi
if [ $opt_linux = true ]; then target_os_linux; compile_main; fi
if [ $opt_windows = true ]; then
target_os_windows