wip lightmapper + GUI improvements
parent
1e65c7cdcf
commit
ab06ce0192
8
MAKE.bat
8
MAKE.bat
|
@ -31,6 +31,7 @@ if "%1"=="help" (
|
|||
echo %0 [test] ; check untracked allocators in V4K
|
||||
echo %0 [todo] ; check for @fixme and @todo
|
||||
echo %0 [v4web] ; sync v4 website
|
||||
echo %0 [swap] ; toggle #line directives on/off
|
||||
echo %0 [split^|join] ; engine/v4k* ^>split^> engine/split/* or engine/split/* ^>join^> engine/v4k*
|
||||
echo %0 [lua] ; execute lua script with v4k
|
||||
echo %0 [amalgamation] ; combine engine/v4k* into a single-header file
|
||||
|
@ -243,6 +244,13 @@ if "%1"=="join" (
|
|||
call tools\join
|
||||
exit /b
|
||||
)
|
||||
if "%1"=="swap" (
|
||||
echo Swapping #line on v4k.h
|
||||
call tools\linswap engine\v4k.h
|
||||
echo Swapping #line on v4k.c
|
||||
call tools\linswap engine\v4k.c
|
||||
exit /b
|
||||
)
|
||||
|
||||
rem fuse binaries and zipfiles
|
||||
if "%1"=="fuse" (
|
||||
|
|
46
bind/v4k.lua
46
bind/v4k.lua
|
@ -1520,17 +1520,23 @@ ffi.cdef([[
|
|||
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 fire;
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 pos;
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 sca;
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*drawrect)(void* userdata, const char *skin, vec4 rect);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 gui_getskinsize(const char *skin);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 gui_getskinsize(const char *skin);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 gui_getskinsize(const char *skin);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 gui_getskinsize(const char *skin, const char *fallback);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 gui_getskinsize(const char *skin, const char *fallback);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 gui_getskinsize(const char *skin, const char *fallback);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in: vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in: vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:API void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||
//lcpp INF [0000] vec4: macro name but used as C declaration in: void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||
|
@ -2991,6 +2997,9 @@ float speed;
|
|||
anim_t* anims;
|
||||
} anims_t;
|
||||
anims_t animations(const char *pathfile, int flags);
|
||||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx;
|
||||
} lightmap_t;
|
||||
typedef struct skybox_t {
|
||||
handle program;
|
||||
mesh_t geometry;
|
||||
|
@ -3315,7 +3324,7 @@ unsigned play;
|
|||
bool paused;
|
||||
struct atlas_t *a;
|
||||
} sprite_t;
|
||||
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3938)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3938)___COUNTER__;;
|
||||
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3945)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3945)___COUNTER__;;
|
||||
void sprite_ctor(sprite_t *s);
|
||||
void sprite_dtor(sprite_t *s);
|
||||
void sprite_tick(sprite_t *s);
|
||||
|
@ -3325,17 +3334,18 @@ enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on
|
|||
void sprite_del(sprite_t *s);
|
||||
void sprite_setanim(sprite_t *s, unsigned name);
|
||||
typedef struct guiskin_t {
|
||||
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
|
||||
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
|
||||
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
|
||||
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
|
||||
void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
|
||||
void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
|
||||
bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
void (*free)(void* userdata);
|
||||
void *userdata;
|
||||
} guiskin_t;
|
||||
void gui_pushskin(guiskin_t skin);
|
||||
void* gui_userdata();
|
||||
vec2 gui_getskinsize(const char *skin);
|
||||
bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||
vec2 gui_getskinsize(const char *skin, const char *fallback);
|
||||
bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
|
||||
vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||
void gui_rect_id(int id, vec4 rect, const char *skin);
|
||||
void gui_label_id(int id, const char *text, vec4 rect);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,13 +45,13 @@ int main() {
|
|||
gui_rect(vec4(40,240, 240, 20*skinned->scale), "vial");
|
||||
gui_rect(vec4(40,240, 160, 14*skinned->scale), "mp");
|
||||
|
||||
vec2 badge_size = gui_getskinsize("badge");
|
||||
vec2 badge_size = gui_getskinsize("badge", 0);
|
||||
badge_size.x += 2; // padding
|
||||
gui_rect(vec4(60+badge_size.x*0,320, 1, 1), "badge");
|
||||
gui_rect(vec4(60+badge_size.x*1,320, 1, 1), "badge");
|
||||
gui_rect(vec4(60+badge_size.x*2,320, 1, 1), "badge_empty");
|
||||
|
||||
vec2 slider_size = gui_getskinsize("slider");
|
||||
vec2 slider_size = gui_getskinsize("slider", 0);
|
||||
gui_slider(vec4(60, 480, 80*skinned->scale, 1), 0, 0.0f, 15.0f, 1.0f, &testval);
|
||||
gui_slider_label(va(FONT_H1 "%.02f", testval2), vec4(60, 480+slider_size.y+10, 120*skinned->scale, 1), 0, -5.0f, 20.0f, 0.0f, &testval2);
|
||||
gui_panel_end();
|
||||
|
|
|
@ -0,0 +1,407 @@
|
|||
#include "v4k.h"
|
||||
|
||||
#define LIGHTMAPPER_IMPLEMENTATION
|
||||
// #define LM_DEBUG_INTERPOLATION
|
||||
#include "3rd_lightmapper.h"
|
||||
|
||||
#define scene_t scene_t2
|
||||
|
||||
typedef struct {
|
||||
float p[3];
|
||||
float t[2];
|
||||
} vertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLuint program;
|
||||
GLint u_lightmap;
|
||||
GLint u_projection;
|
||||
GLint u_view;
|
||||
|
||||
GLuint lightmap;
|
||||
int w, h;
|
||||
|
||||
GLuint vao, vbo, ibo;
|
||||
vertex_t *vertices;
|
||||
unsigned short *indices;
|
||||
unsigned int vertexCount, indexCount;
|
||||
} scene_t;
|
||||
|
||||
static int initScene(scene_t *scene);
|
||||
static void drawScene(scene_t *scene, float *view, float *projection);
|
||||
static void destroyScene(scene_t *scene);
|
||||
|
||||
static int bake(scene_t *scene)
|
||||
{
|
||||
lm_context *ctx = lmCreate(
|
||||
64, // hemisphere resolution (power of two, max=512)
|
||||
0.001f, 100.0f, // zNear, zFar of hemisphere cameras
|
||||
1.0f, 1.0f, 1.0f, // background color (white for ambient occlusion)
|
||||
2, 0.01f, // lightmap interpolation threshold (small differences are interpolated rather than sampled)
|
||||
// check debug_interpolation.tga for an overview of sampled (red) vs interpolated (green) pixels.
|
||||
0.0f); // modifier for camera-to-surface distance for hemisphere rendering.
|
||||
// tweak this to trade-off between interpolated normals quality and other artifacts (see declaration).
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not initialize lightmapper.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w = scene->w, h = scene->h;
|
||||
float *data = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int b = 0; b < 1; b++) {
|
||||
memset(data, 0, w*h*4);
|
||||
lmSetTargetLightmap(ctx, data, w, h, 4);
|
||||
|
||||
lmSetGeometry(ctx, NULL, // no transformation in this example
|
||||
LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t),
|
||||
LM_NONE , NULL , 0 , // no interpolated normals in this example
|
||||
LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t),
|
||||
scene->indexCount, LM_UNSIGNED_SHORT, scene->indices);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
int vp[4];
|
||||
float view[16], projection[16];
|
||||
double lastUpdateTime = 0.0;
|
||||
while (lmBegin(ctx, vp, view, projection))
|
||||
{
|
||||
// render to lightmapper framebuffer
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
drawScene(scene, view, projection);
|
||||
|
||||
// display progress every second (printf is expensive)
|
||||
double time = time_ms() / 1000.0;
|
||||
if (time - lastUpdateTime > 1.0)
|
||||
{
|
||||
lastUpdateTime = time;
|
||||
printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
lmEnd(ctx);
|
||||
// window_swap();
|
||||
}
|
||||
printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
|
||||
}
|
||||
|
||||
lmDestroy(ctx);
|
||||
|
||||
// postprocess texture
|
||||
float *temp = CALLOC(w * h * 4, sizeof(float));
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
lmImageDilate(data, temp, w, h, 4);
|
||||
lmImageDilate(temp, data, w, h, 4);
|
||||
}
|
||||
lmImageSmooth(data, temp, w, h, 4);
|
||||
lmImageDilate(temp, data, w, h, 4);
|
||||
lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
|
||||
FREE(temp);
|
||||
|
||||
// save result to a file
|
||||
if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
|
||||
printf("Saved result.tga\n");
|
||||
|
||||
// upload result
|
||||
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data);
|
||||
FREE(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void fpsCameraViewMatrix(float *view);
|
||||
|
||||
static void mainLoop(scene_t *scene)
|
||||
{
|
||||
glViewport(0, 0, window_width(), window_height());
|
||||
|
||||
// camera for glfw window
|
||||
float view[16], projection[16];
|
||||
fpsCameraViewMatrix(view);
|
||||
perspective44(projection, 45.0f, window_aspect(), 0.01f, 100.0f);
|
||||
|
||||
// draw to screen with a blueish sky
|
||||
glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
drawScene(scene, view, projection);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
window_create(0.5, WINDOW_VSYNC_DISABLED);
|
||||
|
||||
scene_t scene = {0};
|
||||
if (!initScene(&scene))
|
||||
{
|
||||
fprintf(stderr, "Could not initialize scene.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
window_title("AO Baking demo");
|
||||
|
||||
while (window_swap())
|
||||
{
|
||||
mainLoop(&scene);
|
||||
|
||||
if( ui_panel("Lightmapper", PANEL_OPEN) ) {
|
||||
ui_label2("Freecam", "Mouse + W/A/S/D/E/Q keys");
|
||||
ui_label("Warning " ICON_MD_WARNING "@This will take a few seconds and bake a lightmap illuminated by: The mesh itself (initially black) + A white sky (1.0f, 1.0f, 1.0f)");
|
||||
if( ui_button("Bake 1 light bounce") ) {
|
||||
bake(&scene);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
|
||||
destroyScene(&scene);
|
||||
}
|
||||
|
||||
// helpers ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount);
|
||||
|
||||
static int initScene(scene_t *scene)
|
||||
{
|
||||
// load mesh
|
||||
if (!loadSimpleObjFile("demos/art/meshes/gazebo.obj", &scene->vertices, &scene->vertexCount, &scene->indices, &scene->indexCount))
|
||||
{
|
||||
fprintf(stderr, "Error loading obj file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
glGenVertexArrays(1, &scene->vao);
|
||||
glBindVertexArray(scene->vao);
|
||||
|
||||
glGenBuffers(1, &scene->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, scene->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, scene->vertexCount * sizeof(vertex_t), scene->vertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &scene->ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene->ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, scene->indexCount * sizeof(unsigned short), scene->indices, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, p));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, t));
|
||||
|
||||
// create lightmap texture
|
||||
scene->w = 654;
|
||||
scene->h = 654;
|
||||
glGenTextures(1, &scene->lightmap);
|
||||
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
unsigned char emissive[] = { 0, 0, 0, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
|
||||
|
||||
// load shader
|
||||
const char *vp =
|
||||
"in vec3 a_position;\n"
|
||||
"in vec2 a_texcoord;\n"
|
||||
"uniform mat4 u_view;\n"
|
||||
"uniform mat4 u_projection;\n"
|
||||
"out vec2 v_texcoord;\n"
|
||||
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"gl_Position = u_projection * (u_view * vec4(a_position, 1.0));\n"
|
||||
"v_texcoord = a_texcoord;\n"
|
||||
"}\n";
|
||||
|
||||
const char *fp =
|
||||
"in vec2 v_texcoord;\n"
|
||||
"uniform sampler2D u_lightmap;\n"
|
||||
"out vec4 o_color;\n"
|
||||
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"o_color = vec4(texture(u_lightmap, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n"
|
||||
"}\n";
|
||||
|
||||
scene->program = shader(vp, fp, "a_position,a_texcoord", "o_color", NULL);
|
||||
if (!scene->program)
|
||||
{
|
||||
fprintf(stderr, "Error loading shader\n");
|
||||
return 0;
|
||||
}
|
||||
scene->u_view = glGetUniformLocation(scene->program, "u_view");
|
||||
scene->u_projection = glGetUniformLocation(scene->program, "u_projection");
|
||||
scene->u_lightmap = glGetUniformLocation(scene->program, "u_lightmap");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void drawScene(scene_t *scene, float *view, float *projection)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glUseProgram(scene->program);
|
||||
glUniform1i(scene->u_lightmap, 0);
|
||||
glUniformMatrix4fv(scene->u_projection, 1, GL_FALSE, projection);
|
||||
glUniformMatrix4fv(scene->u_view, 1, GL_FALSE, view);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
|
||||
|
||||
glBindVertexArray(scene->vao);
|
||||
glDrawElements(GL_TRIANGLES, scene->indexCount, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
static void destroyScene(scene_t *scene)
|
||||
{
|
||||
FREE(scene->vertices);
|
||||
FREE(scene->indices);
|
||||
glDeleteVertexArrays(1, &scene->vao);
|
||||
glDeleteBuffers(1, &scene->vbo);
|
||||
glDeleteBuffers(1, &scene->ibo);
|
||||
glDeleteTextures(1, &scene->lightmap);
|
||||
glDeleteProgram(scene->program);
|
||||
}
|
||||
|
||||
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount)
|
||||
{
|
||||
FILE *file = fopen(filename, "rt");
|
||||
if (!file)
|
||||
return 0;
|
||||
char line[1024];
|
||||
|
||||
// first pass
|
||||
unsigned int np = 0, nn = 0, nt = 0, nf = 0;
|
||||
while (!feof(file))
|
||||
{
|
||||
fgets(line, 1024, file);
|
||||
if (line[0] == '#') continue;
|
||||
if (line[0] == 'v')
|
||||
{
|
||||
if (line[1] == ' ') { np++; continue; }
|
||||
if (line[1] == 'n') { nn++; continue; }
|
||||
if (line[1] == 't') { nt++; continue; }
|
||||
assert(!"unknown vertex attribute");
|
||||
}
|
||||
if (line[0] == 'f') { nf++; continue; }
|
||||
assert(!"unknown identifier");
|
||||
}
|
||||
assert(np && np == nn && np == nt && nf); // only supports obj files without separately indexed vertex attributes
|
||||
|
||||
// allocate memory
|
||||
*vertexCount = np;
|
||||
*vertices = CALLOC(np, sizeof(vertex_t));
|
||||
*indexCount = nf * 3;
|
||||
*indices = CALLOC(nf * 3, sizeof(unsigned short));
|
||||
|
||||
// second pass
|
||||
fseek(file, 0, SEEK_SET);
|
||||
unsigned int cp = 0, cn = 0, ct = 0, cf = 0;
|
||||
while (!feof(file))
|
||||
{
|
||||
fgets(line, 1024, file);
|
||||
if (line[0] == '#') continue;
|
||||
if (line[0] == 'v')
|
||||
{
|
||||
if (line[1] == ' ') { float *p = (*vertices)[cp++].p; char *e1, *e2; p[0] = (float)strtod(line + 2, &e1); p[1] = (float)strtod(e1, &e2); p[2] = (float)strtod(e2, 0); continue; }
|
||||
if (line[1] == 'n') { /*float *n = (*vertices)[cn++].n; char *e1, *e2; n[0] = (float)strtod(line + 3, &e1); n[1] = (float)strtod(e1, &e2); n[2] = (float)strtod(e2, 0);*/ continue; } // no normals needed
|
||||
if (line[1] == 't') { float *t = (*vertices)[ct++].t; char *e1; t[0] = (float)strtod(line + 3, &e1); t[1] = (float)strtod(e1, 0); continue; }
|
||||
assert(!"unknown vertex attribute");
|
||||
}
|
||||
if (line[0] == 'f')
|
||||
{
|
||||
unsigned short *tri = (*indices) + cf;
|
||||
cf += 3;
|
||||
char *e1, *e2, *e3 = line + 1;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
unsigned long pi = strtoul(e3 + 1, &e1, 10);
|
||||
assert(e1[0] == '/');
|
||||
unsigned long ti = strtoul(e1 + 1, &e2, 10);
|
||||
assert(e2[0] == '/');
|
||||
unsigned long ni = strtoul(e2 + 1, &e3, 10);
|
||||
assert(pi == ti && pi == ni);
|
||||
tri[i] = (unsigned short)(pi - 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
assert(!"unknown identifier");
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fpsCameraViewMatrix(float *view)
|
||||
{
|
||||
// initial camera config
|
||||
static float position[] = { 0.0f, 0.3f, 1.5f };
|
||||
static float rotation[] = { 0.0f, 0.0f };
|
||||
|
||||
// mouse look
|
||||
static double lastMouse[] = { 0.0, 0.0 };
|
||||
double mouse_coord[2];
|
||||
mouse_coord[0] = input(MOUSE_X);
|
||||
mouse_coord[1] = input(MOUSE_Y);
|
||||
if (input(MOUSE_L))
|
||||
{
|
||||
rotation[0] += (float)(mouse_coord[1] - lastMouse[1]) * -0.2f;
|
||||
rotation[1] += (float)(mouse_coord[0] - lastMouse[0]) * -0.2f;
|
||||
}
|
||||
lastMouse[0] = mouse_coord[0];
|
||||
lastMouse[1] = mouse_coord[1];
|
||||
|
||||
float rotationY[16], rotationX[16], rotationYX[16];
|
||||
rotation44(rotationX, rotation[0], 1.0f, 0.0f, 0.0f);
|
||||
rotation44(rotationY, rotation[1], 0.0f, 1.0f, 0.0f);
|
||||
multiply44x2(rotationYX, rotationY, rotationX);
|
||||
|
||||
// keyboard movement (WSADEQ)
|
||||
float speed = input(KEY_SHIFT) ? 0.1f : 0.01f;
|
||||
vec3 movement = {0};
|
||||
if (input(KEY_W)) movement.z -= speed;
|
||||
if (input(KEY_S)) movement.z += speed;
|
||||
if (input(KEY_A)) movement.x -= speed;
|
||||
if (input(KEY_D)) movement.x += speed;
|
||||
if (input(KEY_E)) movement.y -= speed;
|
||||
if (input(KEY_Q)) movement.y += speed;
|
||||
|
||||
vec3 worldMovement = transform344(rotationYX, movement);
|
||||
position[0] += worldMovement.x;
|
||||
position[1] += worldMovement.y;
|
||||
position[2] += worldMovement.z;
|
||||
|
||||
// construct view matrix
|
||||
float inverseRotation[16], inverseTranslation[16];
|
||||
transpose44(inverseRotation, rotationYX);
|
||||
translation44(inverseTranslation, -position[0], -position[1], -position[2]);
|
||||
multiply44x2(view, inverseRotation, inverseTranslation); // = inverse(translation(position) * rotationYX);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#######################################################################
|
||||
76702 17.93% rendered hemicubes integrated to lightmap texels.
|
||||
179388 41.94% interpolated lightmap texels.
|
||||
171626 40.13% wasted lightmap texels.
|
||||
|
||||
29.95% of used texels were rendered.
|
||||
#######################################################################
|
||||
Finished baking 731 triangles.
|
||||
Saved result.tga
|
||||
|
||||
vs
|
||||
|
||||
#######################################################################
|
||||
124 0.05% rendered hemicubes integrated to lightmap texels.
|
||||
201 0.08% interpolated lightmap texels.
|
||||
261947 99.88% wasted lightmap texels.
|
||||
|
||||
38.15% of used texels were rendered.
|
||||
#######################################################################
|
||||
Finished baking 731 triangles.
|
||||
Saved result.tga
|
||||
|
||||
#endif
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#include "v4k.h" // Minimal C sample
|
||||
|
||||
__thread int foo=0;
|
||||
|
||||
int worker(void *ud) {
|
||||
printf("thread:%d\n", foo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
foo=1;
|
||||
printf("main:%d\n", foo);
|
||||
thread_destroy(thread(worker, NULL));
|
||||
return 0;
|
||||
}
|
1852
engine/joint/v4k.h
1852
engine/joint/v4k.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -53,6 +53,7 @@
|
|||
#define BQ_PLATFORM_IMPLEMENTATION // websocket
|
||||
#define BQ_WEBSOCKET_IMPLEMENTATION // websocket
|
||||
#define XML_C // xml
|
||||
#define LIGHTMAPPER_IMPLEMENTATION // lightmapper
|
||||
#ifdef __APPLE__
|
||||
#define MA_NO_RUNTIME_LINKING // miniaudio osx
|
||||
#define _GLFW_COCOA // glfw osx
|
||||
|
@ -217,4 +218,6 @@ static char *ui_filter = 0;
|
|||
{{FILE:3rd_lite_sys.h}}
|
||||
{{FILE:3rd_lite.h}}
|
||||
|
||||
{{FILE:3rd_lightmapper.h}}
|
||||
|
||||
#endif // V4K_3RD
|
||||
|
|
|
@ -118,17 +118,23 @@ void *gui_userdata() {
|
|||
return last_skin->userdata;
|
||||
}
|
||||
|
||||
vec2 gui_getskinsize(const char *skin) {
|
||||
vec2 gui_getskinsize(const char *skin, const char *fallback) {
|
||||
vec2 size={0};
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, fallback, &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool gui_ismouseinrect(const char *skin, vec4 rect) {
|
||||
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
|
||||
bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect) {
|
||||
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, fallback, rect);
|
||||
return false;
|
||||
}
|
||||
|
||||
vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect) {
|
||||
vec4 scissor = rect;
|
||||
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, fallback, rect, &scissor);
|
||||
return scissor;
|
||||
}
|
||||
|
||||
static
|
||||
gui_state_t *gui_getstate(int id) {
|
||||
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
|
||||
|
@ -138,8 +144,8 @@ gui_state_t *gui_getstate(int id) {
|
|||
void gui_panel_id(int id, vec4 rect, const char *skin) {
|
||||
(void)id;
|
||||
vec4 scissor={0, 0, window_width(), window_height()};
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
|
||||
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
|
||||
scissor = gui_getscissorrect(skin, NULL, rect);
|
||||
|
||||
if (!array_count(scissor_rects))
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
@ -164,7 +170,7 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
|
|||
|
||||
skin=skin?skin:"button";
|
||||
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
|
||||
if (gui_ismouseinrect(btn, r)) {
|
||||
if (gui_ismouseinrect(btn, skin, r)) {
|
||||
if (input_up(MOUSE_L) && entry->held) {
|
||||
was_clicked=1;
|
||||
}
|
||||
|
@ -174,24 +180,27 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
|
|||
entry->hover = true;
|
||||
}
|
||||
}
|
||||
else if (input_up(MOUSE_L) && entry->held) {
|
||||
entry->held = false;
|
||||
any_widget_used = false;
|
||||
}
|
||||
else {
|
||||
entry->hover = false;
|
||||
}
|
||||
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
|
||||
if (input_up(MOUSE_L) && entry->held) {
|
||||
entry->held = false;
|
||||
any_widget_used = false;
|
||||
}
|
||||
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, skin, r);
|
||||
|
||||
return was_clicked;
|
||||
}
|
||||
|
||||
bool gui_button_label_id(int id, const char *text, vec4 rect, const char *skin) {
|
||||
gui_state_t *entry = gui_getstate(id);
|
||||
bool state = gui_button_id(id, rect, skin);
|
||||
vec2 buttonsize={0};
|
||||
skin=skin?skin:"button";
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &buttonsize);
|
||||
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
|
||||
buttonsize = gui_getskinsize(btn, skin);
|
||||
|
||||
vec2 textsize = font_rect(text);
|
||||
vec2 pos;
|
||||
|
@ -224,7 +233,8 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
|
|||
|
||||
skin = skin?skin:"slider";
|
||||
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
|
||||
if (gui_ismouseinrect(skin, rect) && !any_widget_used) {
|
||||
char *fbcursor = va("%s_cursor", skin);
|
||||
if (gui_ismouseinrect(skin, NULL, rect) && !any_widget_used) {
|
||||
any_widget_used = entry->held = input_held(MOUSE_L);
|
||||
entry->hover = true;
|
||||
}
|
||||
|
@ -237,13 +247,12 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
|
|||
}
|
||||
|
||||
float old_value = *value;
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
|
||||
|
||||
vec2 slidersize={0}, cursorsize={0};
|
||||
vec4 usablerect=rect;
|
||||
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
|
||||
vec4 usablerect = gui_getscissorrect(skin, NULL, rect);
|
||||
slidersize = gui_getskinsize(skin, NULL);
|
||||
cursorsize = gui_getskinsize(cursorskin, fbcursor);
|
||||
if (entry->held) {
|
||||
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
|
||||
}
|
||||
|
@ -254,7 +263,7 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
|
|||
cursorrect.y += cursorpos.y;
|
||||
cursorrect.z = cursorsize.x;
|
||||
cursorrect.w = cursorsize.y;
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, fbcursor, cursorrect);
|
||||
|
||||
return entry->held && (old_value!=*value);
|
||||
}
|
||||
|
@ -263,7 +272,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
|
|||
bool state = gui_slider_id(id, rect, skin, min, max, step, value);
|
||||
vec2 slidersize={0};
|
||||
skin=skin?skin:"slider";
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
|
||||
slidersize = gui_getskinsize(skin, NULL);
|
||||
|
||||
vec2 textsize = font_rect(text);
|
||||
vec2 pos;
|
||||
|
@ -276,7 +285,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
|
|||
|
||||
void gui_rect_id(int id, vec4 r, const char *skin) {
|
||||
(void)id;
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, r);
|
||||
}
|
||||
|
||||
void gui_label_id(int id, const char *text, vec4 rect) {
|
||||
|
@ -300,7 +309,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
|
|||
for (int i = 0; i < array_count(a->slices); i++)
|
||||
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
||||
return &a->slice_frames[a->slices[i].frames[0]];
|
||||
PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||
// PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -311,9 +320,10 @@ void skinned_draw_missing_rect(vec4 r) {
|
|||
}
|
||||
|
||||
static
|
||||
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
|
||||
bool skinned_ismouseinrect(void *userdata, const char *skin, const char *fallback, vec4 r) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (!f) return false;
|
||||
|
||||
vec4 outer = f->bounds;
|
||||
|
@ -396,18 +406,20 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
|
|||
}
|
||||
|
||||
static
|
||||
void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
|
||||
void skinned_draw_rect(void* userdata, const char *skin, const char *fallback, vec4 r) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (!f) skinned_draw_missing_rect(r);
|
||||
else skinned_draw_sprite(a->scale, &a->atlas, f, r);
|
||||
}
|
||||
|
||||
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
|
||||
void skinned_getskinsize(void *userdata, const char *skin, const char *fallback, vec2 *size) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (f) {
|
||||
size->x = (f->bounds.z-f->bounds.x)*a->scale;
|
||||
size->y = (f->bounds.w-f->bounds.y)*a->scale;
|
||||
|
@ -415,9 +427,10 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
|
|||
}
|
||||
|
||||
static
|
||||
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
|
||||
void skinned_getscissorrect(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (!f) return;
|
||||
|
||||
*dims = rect;
|
||||
|
|
|
@ -2,18 +2,19 @@
|
|||
// game ui
|
||||
|
||||
typedef struct guiskin_t {
|
||||
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
|
||||
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
|
||||
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
|
||||
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
|
||||
void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
|
||||
void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
|
||||
bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
void (*free)(void* userdata);
|
||||
void *userdata;
|
||||
} guiskin_t;
|
||||
|
||||
API void gui_pushskin(guiskin_t skin);
|
||||
API void* gui_userdata();
|
||||
API vec2 gui_getskinsize(const char *skin);
|
||||
API bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||
API vec2 gui_getskinsize(const char *skin, const char *fallback);
|
||||
API bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
|
||||
API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
// --
|
||||
API void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||
API void gui_rect_id(int id, vec4 rect, const char *skin);
|
||||
|
|
|
@ -577,6 +577,13 @@ typedef struct anims_t {
|
|||
|
||||
API anims_t animations(const char *pathfile, int flags);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// lightmapping utils
|
||||
|
||||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx; // private
|
||||
} lightmap_t;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// skyboxes
|
||||
|
||||
|
|
1765
engine/v4k
1765
engine/v4k
File diff suppressed because it is too large
Load Diff
67
engine/v4k.c
67
engine/v4k.c
|
@ -11128,17 +11128,23 @@ void *gui_userdata() {
|
|||
return last_skin->userdata;
|
||||
}
|
||||
|
||||
vec2 gui_getskinsize(const char *skin) {
|
||||
vec2 gui_getskinsize(const char *skin, const char *fallback) {
|
||||
vec2 size={0};
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, fallback, &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool gui_ismouseinrect(const char *skin, vec4 rect) {
|
||||
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
|
||||
bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect) {
|
||||
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, fallback, rect);
|
||||
return false;
|
||||
}
|
||||
|
||||
vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect) {
|
||||
vec4 scissor = rect;
|
||||
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, fallback, rect, &scissor);
|
||||
return scissor;
|
||||
}
|
||||
|
||||
static
|
||||
gui_state_t *gui_getstate(int id) {
|
||||
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
|
||||
|
@ -11148,8 +11154,8 @@ gui_state_t *gui_getstate(int id) {
|
|||
void gui_panel_id(int id, vec4 rect, const char *skin) {
|
||||
(void)id;
|
||||
vec4 scissor={0, 0, window_width(), window_height()};
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
|
||||
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
|
||||
scissor = gui_getscissorrect(skin, NULL, rect);
|
||||
|
||||
if (!array_count(scissor_rects))
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
@ -11174,7 +11180,7 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
|
|||
|
||||
skin=skin?skin:"button";
|
||||
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
|
||||
if (gui_ismouseinrect(btn, r)) {
|
||||
if (gui_ismouseinrect(btn, skin, r)) {
|
||||
if (input_up(MOUSE_L) && entry->held) {
|
||||
was_clicked=1;
|
||||
}
|
||||
|
@ -11184,24 +11190,27 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
|
|||
entry->hover = true;
|
||||
}
|
||||
}
|
||||
else if (input_up(MOUSE_L) && entry->held) {
|
||||
entry->held = false;
|
||||
any_widget_used = false;
|
||||
}
|
||||
else {
|
||||
entry->hover = false;
|
||||
}
|
||||
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
|
||||
if (input_up(MOUSE_L) && entry->held) {
|
||||
entry->held = false;
|
||||
any_widget_used = false;
|
||||
}
|
||||
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, skin, r);
|
||||
|
||||
return was_clicked;
|
||||
}
|
||||
|
||||
bool gui_button_label_id(int id, const char *text, vec4 rect, const char *skin) {
|
||||
gui_state_t *entry = gui_getstate(id);
|
||||
bool state = gui_button_id(id, rect, skin);
|
||||
vec2 buttonsize={0};
|
||||
skin=skin?skin:"button";
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &buttonsize);
|
||||
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
|
||||
buttonsize = gui_getskinsize(btn, skin);
|
||||
|
||||
vec2 textsize = font_rect(text);
|
||||
vec2 pos;
|
||||
|
@ -11234,7 +11243,8 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
|
|||
|
||||
skin = skin?skin:"slider";
|
||||
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
|
||||
if (gui_ismouseinrect(skin, rect) && !any_widget_used) {
|
||||
char *fbcursor = va("%s_cursor", skin);
|
||||
if (gui_ismouseinrect(skin, NULL, rect) && !any_widget_used) {
|
||||
any_widget_used = entry->held = input_held(MOUSE_L);
|
||||
entry->hover = true;
|
||||
}
|
||||
|
@ -11247,13 +11257,12 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
|
|||
}
|
||||
|
||||
float old_value = *value;
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
|
||||
|
||||
vec2 slidersize={0}, cursorsize={0};
|
||||
vec4 usablerect=rect;
|
||||
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
|
||||
vec4 usablerect = gui_getscissorrect(skin, NULL, rect);
|
||||
slidersize = gui_getskinsize(skin, NULL);
|
||||
cursorsize = gui_getskinsize(cursorskin, fbcursor);
|
||||
if (entry->held) {
|
||||
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
|
||||
}
|
||||
|
@ -11264,7 +11273,7 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
|
|||
cursorrect.y += cursorpos.y;
|
||||
cursorrect.z = cursorsize.x;
|
||||
cursorrect.w = cursorsize.y;
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, fbcursor, cursorrect);
|
||||
|
||||
return entry->held && (old_value!=*value);
|
||||
}
|
||||
|
@ -11273,7 +11282,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
|
|||
bool state = gui_slider_id(id, rect, skin, min, max, step, value);
|
||||
vec2 slidersize={0};
|
||||
skin=skin?skin:"slider";
|
||||
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
|
||||
slidersize = gui_getskinsize(skin, NULL);
|
||||
|
||||
vec2 textsize = font_rect(text);
|
||||
vec2 pos;
|
||||
|
@ -11286,7 +11295,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
|
|||
|
||||
void gui_rect_id(int id, vec4 r, const char *skin) {
|
||||
(void)id;
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
|
||||
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, r);
|
||||
}
|
||||
|
||||
void gui_label_id(int id, const char *text, vec4 rect) {
|
||||
|
@ -11310,7 +11319,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
|
|||
for (int i = 0; i < array_count(a->slices); i++)
|
||||
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
|
||||
return &a->slice_frames[a->slices[i].frames[0]];
|
||||
PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||
// PRINTF("slice name: '%s' is missing in atlas!\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -11321,9 +11330,10 @@ void skinned_draw_missing_rect(vec4 r) {
|
|||
}
|
||||
|
||||
static
|
||||
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
|
||||
bool skinned_ismouseinrect(void *userdata, const char *skin, const char *fallback, vec4 r) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (!f) return false;
|
||||
|
||||
vec4 outer = f->bounds;
|
||||
|
@ -11406,18 +11416,20 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
|
|||
}
|
||||
|
||||
static
|
||||
void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
|
||||
void skinned_draw_rect(void* userdata, const char *skin, const char *fallback, vec4 r) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (!f) skinned_draw_missing_rect(r);
|
||||
else skinned_draw_sprite(a->scale, &a->atlas, f, r);
|
||||
}
|
||||
|
||||
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
|
||||
void skinned_getskinsize(void *userdata, const char *skin, const char *fallback, vec2 *size) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (f) {
|
||||
size->x = (f->bounds.z-f->bounds.x)*a->scale;
|
||||
size->y = (f->bounds.w-f->bounds.y)*a->scale;
|
||||
|
@ -11425,9 +11437,10 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
|
|||
}
|
||||
|
||||
static
|
||||
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
|
||||
void skinned_getscissorrect(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims) {
|
||||
skinned_t *a = C_CAST(skinned_t*, userdata);
|
||||
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
|
||||
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
|
||||
if (!f) return;
|
||||
|
||||
*dims = rect;
|
||||
|
|
20
engine/v4k.h
20
engine/v4k.h
|
@ -3638,6 +3638,13 @@ typedef struct anims_t {
|
|||
|
||||
API anims_t animations(const char *pathfile, int flags);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// lightmapping utils
|
||||
|
||||
typedef struct lightmap_t {
|
||||
struct lm_context *ctx; // private
|
||||
} lightmap_t;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// skyboxes
|
||||
|
||||
|
@ -4184,18 +4191,19 @@ API void sprite_setanim(sprite_t *s, unsigned name);
|
|||
// game ui
|
||||
|
||||
typedef struct guiskin_t {
|
||||
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
|
||||
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
|
||||
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
|
||||
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
|
||||
void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
|
||||
void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
|
||||
bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
|
||||
void (*free)(void* userdata);
|
||||
void *userdata;
|
||||
} guiskin_t;
|
||||
|
||||
API void gui_pushskin(guiskin_t skin);
|
||||
API void* gui_userdata();
|
||||
API vec2 gui_getskinsize(const char *skin);
|
||||
API bool gui_ismouseinrect(const char *skin, vec4 rect);
|
||||
API vec2 gui_getskinsize(const char *skin, const char *fallback);
|
||||
API bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
|
||||
API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
|
||||
// --
|
||||
API void gui_panel_id(int id, vec4 rect, const char *skin);
|
||||
API void gui_rect_id(int id, vec4 rect, const char *skin);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#include "v4k.c"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s [file]\n", argv[0]);
|
||||
fprintf(stderr, "file: %s\n", "source file to process");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *buf = file_read(argv[1]);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "error: %s\n", "file does not exist!");
|
||||
return 2;
|
||||
}
|
||||
file_delete(argv[1]);
|
||||
|
||||
// determine swap mode
|
||||
char mode = strstri(buf, "//@#line 1 \"") == NULL;
|
||||
char **lines = strsplit(buf, "\n");
|
||||
|
||||
for (int i = 0; i < array_count(lines); i++) {
|
||||
char *line = STRDUP(lines[i]);
|
||||
if (!mode) {
|
||||
strrepl(&line, "//@#line 1 \"", "#line 1 \"");
|
||||
} else {
|
||||
strrepl(&line, "#line 1 \"", "//@#line 1 \"");
|
||||
}
|
||||
|
||||
// printf("%s\n", line);
|
||||
file_append(argv[1], line, strlen(line));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -3,8 +3,8 @@
|
|||
[
|
||||
{
|
||||
"path": ".",
|
||||
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k", "engine/joint/", "engine/split/"],
|
||||
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/split/**", "_mirror/**"]
|
||||
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k", "engine/joint/", "engine/split/v4k_*"],
|
||||
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/split/v4k_**", "_mirror/**"]
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
|
|
Loading…
Reference in New Issue