idk a lot of stuff changed

This commit is contained in:
sam 2024-08-31 17:42:56 +12:00
parent 73226349db
commit 1995bb7cae
56 changed files with 36253 additions and 118 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
.cache/
.session.vim
log.txt
*.exe
./gear
compile_commands.json

View file

@ -2,7 +2,8 @@ BINARY=gear
SHADERC=sokol-shdc
CFLAGS=-I. -Iinclude -Wall -Wextra -Werror -Wno-header-guard
CFLAGS=-I. -Iinclude -Wall -Wextra -Werror -Wno-header-guard -Wno-comment -g
LDFLAGS=-g
SHADER_FLAGS=--slang glsl430:hlsl5:metal_macos
C_FILES=$(shell find -L * -type f -name '*.c')

BIN
assets/OpenSans-Regular.ttf Normal file

Binary file not shown.

BIN
gear Executable file

Binary file not shown.

BIN
happi.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

22
include/fast_obj/LICENSE Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2018 thisistherk
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1584
include/fast_obj/fast_obj.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,8 @@
#include <assert.h>
#include <slibs/slibs.h>
#include <HandmadeMath/HandmadeMath.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
@ -23,4 +25,14 @@ typedef size_t sz;
typedef float f32;
typedef double f64;
typedef HMM_Vec2 vec2;
typedef HMM_Vec3 vec3;
typedef HMM_Vec4 vec4;
typedef HMM_Quat quat;
typedef HMM_Mat2 mat2;
typedef HMM_Mat3 mat3;
typedef HMM_Mat4 mat4;
#define SL_SG_RANGE(x) (sg_range){ .ptr = x.data, .size = x.size * sizeof(*x.data) }
#endif

23
include/gear/camera.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef __G_CAMERA_H__
#define __G_CAMERA_H__
#include <gear/base.h>
typedef struct g_camera {
vec3 position;
vec3 rotation;
float fov;
float near;
float far;
} g_camera;
// src/camera/create.c
g_camera* g_camera_create(vec3 position, vec3 rotation, float fov);
// src/camera/calculations.c
mat4 g_camera_matrix(g_camera* camera);
// src/camera/destroy.c
void g_camera_destroy(g_camera* camera);
#endif

View file

@ -10,18 +10,19 @@ typedef struct g_color {
u8 a;
} g_color;
#define G_COLOR_TO_U32(color) *((u32*)(&color))
#define G_COLOR_TO_FLOAT_ARR(color) { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f }
#define G_FLOAT_ARR_TO_COLOR(float) { (u8)(float[0] * 255), (u8)(float[1] * 255), (u8)(float[2] * 255), (u8)(float[3] * 255) }
#define G_WHITE { 255, 255, 255, 255 }
#define G_BLACK { 0, 0, 0, 255 }
#define G_WHITE (g_color){ 255, 255, 255, 255 }
#define G_BLACK (g_color){ 0, 0, 0, 255 }
#define G_RED { 255, 0, 0, 255 }
#define G_GREEN { 0, 255, 0, 255 }
#define G_BLUE { 0, 0, 255, 255 }
#define G_RED (g_color){ 255, 0, 0, 255 }
#define G_GREEN (g_color){ 0, 255, 0, 255 }
#define G_BLUE (g_color){ 0, 0, 255, 255 }
#define G_YELLOW { 255, 255, 0, 255 }
#define G_CYAN { 0, 255, 255, 255 }
#define G_MAGENTA { 255, 0, 255, 255 }
#define G_YELLOW (g_color){ 255, 255, 0, 255 }
#define G_CYAN (g_color){ 0, 255, 255, 255 }
#define G_MAGENTA (g_color){ 255, 0, 255, 255 }
#endif

View file

@ -0,0 +1,35 @@
#ifndef __G_MODELS_H__
#define __G_MODELS_H__
#include <gear/base.h>
#include <gear/graphics/color.h>
#include <sokol/sokol_gfx.h>
typedef struct g_vertex {
float x, y, z;
g_color color;
int16_t u, v;
} g_vertex;
typedef u32 g_index;
typedef sl_vec(g_vertex) g_vertex_vec;
typedef sl_vec(g_index) g_index_vec;
typedef struct g_model {
g_vertex_vec vertices;
g_index_vec indices;
sg_buffer vertex_buffer;
sg_buffer index_buffer;
} g_model;
// src/graphics/models/create.c
g_model* g_model_create(g_vertex_vec* vertices, g_index_vec* indices);
// src/graphics/models/load.c
// g_model* g_model_load(const char* filename);
// src/graphics/models/destroy.c
void g_model_destroy(g_model* model);
#endif

View file

@ -0,0 +1,13 @@
#ifndef __G_PIPELINE_H__
#define __G_PIPELINE_H__
#include <gear/graphics/renderer.h>
#include <sokol/sokol_gfx.h>
// src/graphics/renderer/pipeline/create.c
sg_pipeline g_pipeline_create(sg_shader shader, sg_vertex_layout_state layout);
// src/graphics/renderer/pipeline/use.c
void g_pipeline_bind(g_renderer* renderer, sg_pipeline pipeline);
#endif

View file

@ -7,6 +7,7 @@
typedef struct g_renderer {
sg_pass_action pass_action;
u32 bound_pipeline_id;
} g_renderer;
typedef struct g_renderer_object {
@ -15,6 +16,14 @@ typedef struct g_renderer_object {
} g_renderer_object;
// src/graphics/renderer/create.c
g_renderer g_renderer_create(g_color clear_color);
g_renderer* g_renderer_create(g_color clear_color);
// src/graphics/renderer/renderer.c
void g_renderer_begin(g_renderer* renderer);
void g_renderer_draw(g_renderer* renderer, g_renderer_object object, u32 elements);
void g_renderer_end(g_renderer* renderer);
// src/graphics/renderer/destroy.c
void g_renderer_destroy(g_renderer* renderer);
#endif

View file

@ -7,11 +7,17 @@
#include <sokol/sokol_gfx.h>
typedef struct g_texture {
i32 width;
i32 height;
sg_image image;
sg_sampler sampler;
} g_texture;
// src/textures/create.c
// src/graphics/textures/create.c
g_texture* g_texture_create(g_image* image);
g_texture* g_texture_create_filtered(g_image* image, sg_filter min_filter, sg_filter mag_filter);
// src/graphics/textures/destroy.c
void g_texture_destroy(g_texture* texture);
#endif

View file

@ -24,6 +24,6 @@ g_image* g_image_default();
g_image* g_image_load(const char* filename);
// src/images/destroy.c
void g_image_free(g_image* image);
void g_image_destroy(g_image* image);
#endif

23
include/gear/ui/console.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef __G_CONSOLE_H__
#define __G_CONSOLE_H__
#include <gear/base.h>
#include <gear/ui/gui.h>
#include <log.c/log.h>
typedef struct g_console {
sl_string input;
sl_string output;
void (*log_callback)(log_Event* event);
} g_console;
// src/ui/console/create.c
g_gui_layer* g_console_create();
// src/ui/console/draw.c
void g_console_draw(g_gui_context* ctx, g_gui_layer* console);
// src/ui/console/destroy.c
void g_console_destroy(void* console);
#endif

43
include/gear/ui/gui.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef __G_GUI_H__
#define __G_GUI_H__
#include <gear/base.h>
#include <sokol/sokol_gfx.h>
#include <sokol/sokol_app.h>
#include <nuklear/nuklear_defines.h>
#include <sokol/util/sokol_nuklear.h>
typedef struct nk_context g_gui_context;
typedef void (*g_gui_layer_destroy_function)(void* data);
typedef struct g_gui_layer {
const char* name;
void* data;
void (*draw)(g_gui_context* ctx, struct g_gui_layer* layer);
g_gui_layer_destroy_function destroy;
} g_gui_layer;
typedef sl_vec(g_gui_layer*) g_gui_layers;
typedef g_gui_layer* (*g_gui_layer_create_function)();
typedef struct g_gui {
g_gui_layers layers;
g_gui_context* ctx;
} g_gui;
// src/ui/gui/create.c
g_gui* g_gui_create();
// src/ui/gui/update.c
void g_gui_update(g_gui* gui);
// src/ui/gui/render.c
void g_gui_render(i32 width, i32 height);
// src/ui/gui/layers.c
void g_gui_add_layer(g_gui_layers* layers, g_gui_layer_create_function create_function, g_gui_layer_destroy_function destroy_function);
// src/ui/gui/destroy.c
void g_gui_destroy(g_gui* gui);
#endif

20
include/log.c/LICENSE Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2020 rxi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

50
include/log.c/log.h Normal file
View file

@ -0,0 +1,50 @@
/**
* Copyright (c) 2020 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See `log.c` for details.
*/
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <time.h>
#define LOG_VERSION "0.1.0"
typedef struct {
va_list ap;
const char *fmt;
const char *file;
struct tm *time;
void *udata;
int line;
int level;
} log_Event;
typedef void (*log_LogFn)(log_Event *ev);
typedef void (*log_LockFn)(bool lock, void *udata);
enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
const char* log_level_string(int level);
void log_set_lock(log_LockFn fn, void *udata);
void log_set_level(int level);
void log_set_quiet(bool enable);
int log_add_callback(log_LogFn fn, void *udata, int level);
int log_add_fp(FILE *fp, int level);
void log_log(int level, const char *file, int line, const char *fmt, ...);
#endif

40
include/nuklear/LICENSE Normal file
View file

@ -0,0 +1,40 @@
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Micha Mettke
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------

30901
include/nuklear/nuklear.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_STANDARD_VARARGS
#include <nuklear/nuklear.h>

@ -1 +1 @@
Subproject commit 112d98edcdd9780dbe101674568b9e6450e01d1a
Subproject commit 60342695a4b47cc383120cd5883101ea9412557d

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,15 @@
@vs vs
in vec4 position;
in vec4 pos;
in vec4 color0;
in vec2 texcoord0;
out vec2 uv;
out vec4 color;
void main() {
gl_Position = position;
gl_Position = pos;
uv = texcoord0;
color = color0;
}
@end
@ -15,10 +18,11 @@ uniform texture2D tex;
uniform sampler smp;
in vec2 uv;
in vec4 color;
out vec4 frag_color;
void main() {
frag_color = texture(sampler2D(tex, smp), uv);
frag_color = texture(sampler2D(tex, smp), uv) * color;
}
@end

19
src/camera/calculations.c Normal file
View file

@ -0,0 +1,19 @@
#include <gear/camera.h>
#include <sokol/sokol_app.h>
mat4 g_camera_matrix(g_camera* camera) {
mat4 rotation_x = HMM_Rotate_RH(HMM_AngleDeg(camera->rotation.X), HMM_V3(1.0f, 0.0f, 0.0f));
mat4 rotation_y = HMM_Rotate_RH(HMM_AngleDeg(camera->rotation.Y), HMM_V3(0.0f, 1.0f, 0.0f));
mat4 rotation_z = HMM_Rotate_RH(HMM_AngleDeg(camera->rotation.Z), HMM_V3(0.0f, 0.0f, 1.0f));
mat4 rotation = HMM_Mul(HMM_Mul(rotation_z, rotation_y), rotation_x);
mat4 translation = HMM_Translate(camera->position);
mat4 view = HMM_Mul(rotation, translation);
mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(camera->fov),
sapp_widthf() / sapp_heightf(), camera->near, camera->far);
HMM_Mat4 view_proj = HMM_Mul(projection, view);
return view_proj;
}

21
src/camera/create.c Normal file
View file

@ -0,0 +1,21 @@
#include <gear/camera.h>
#include <log.c/log.h>
g_camera* g_camera_create(vec3 position, vec3 rotation, float fov) {
g_camera* camera = calloc(1, sizeof(g_camera));
if(camera != NULL) {
log_info("Camera allocated successfully");
log_debug("Camera pointer: %p", camera);
camera->position = position;
camera->rotation = rotation;
camera->fov = fov;
camera->near = 0.1f;
camera->far = 1000.0f;
} else {
log_fatal("Failed to allocate camera");
exit(EXIT_FAILURE);
}
return camera;
}

8
src/camera/destroy.c Normal file
View file

@ -0,0 +1,8 @@
#include <gear/camera.h>
#include <log.c/log.h>
void g_camera_destroy(g_camera* camera) {
free(camera);
log_debug("Freed camera: %p", camera);
}

View file

@ -0,0 +1,37 @@
#include <gear/graphics/models.h>
#include <log.c/log.h>
g_model* g_model_create(g_vertex_vec* vertices, g_index_vec* indices) {
g_model* model = calloc(1, sizeof(g_model));
if(model != NULL) {
log_info("Model allocated successfully");
log_debug("Model pointer: %p", model);
if(vertices != NULL) {
for(sz i = 0; i < vertices->size; i++) {
sl_vec_push(model->vertices, vertices->data[i]);
}
model->vertex_buffer = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_VERTEXBUFFER,
.data = SL_SG_RANGE(model->vertices)
});
}
if(indices != NULL) {
for(sz i = 0; i < indices->size; i++) {
sl_vec_push(model->indices, indices->data[i]);
}
model->index_buffer = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_INDEXBUFFER,
.data = SL_SG_RANGE(model->indices)
});
}
} else {
log_fatal("Failed to allocate model");
exit(EXIT_FAILURE);
}
return model;
}

View file

@ -0,0 +1,10 @@
#include <gear/graphics/models.h>
#include <log.c/log.h>
void g_model_destroy(g_model* model) {
sl_vec_free(model->indices);
sl_vec_free(model->vertices);
free(model);
log_debug("Freed model: %p", model);
}

View file

@ -0,0 +1,33 @@
/*#include <gear/graphics/models.h>
#include <gear/graphics/color.h>
#include <fast_obj/fast_obj.h>
g_model* g_model_load(const char* filename) {
fastObjMesh* mesh = fast_obj_read(filename);
fastObjMaterial mat = mesh->materials[0];
g_vertex_vec vertices = { 0 };
printf("load: %d positions\n", mesh->position_count);
for(sz i = 1; i < mesh->position_count; i++) {
g_vertex vertex = {
.x = mesh->positions[i * 3],
.y = mesh->positions[i * 3 + 1],
.z = mesh->positions[i * 3 + 2],
.color = (g_color){ mat.Kd[0] * 255, mat.Kd[1] * 255, mat.Kd[2] * 255, 255 },
.u = mesh->texcoords[i * 2] * 32767,
.v = mesh->texcoords[i * 2 + 1] * 32767
};
sl_vec_push(vertices, vertex);
}
g_index_vec indices = { 0 };
printf("load: %d indices\n", mesh->index_count);
for(sz i = 0; i < mesh->index_count; i++) {
printf("index (%u) points to\n", mesh->indices[i].p);
sl_vec_push(indices, mesh->indices[i].p - 1);
}
return g_model_create(&vertices, &indices);
}*/

View file

@ -1,18 +1,25 @@
#include <gear/graphics/renderer.h>
#include <log.c/log.h>
g_renderer g_renderer_create(g_color clear_color) {
g_renderer renderer;
memset(&renderer, 0, sizeof(g_renderer));
g_renderer* g_renderer_create(g_color clear_color) {
sg_color_attachment_action color_action = {
.load_action = SG_LOADACTION_CLEAR,
.clear_value = G_COLOR_TO_FLOAT_ARR(clear_color),
};
renderer.pass_action = (sg_pass_action){
.colors = { color_action, color_action, color_action, color_action },
.depth = { .load_action = SG_LOADACTION_CLEAR, .clear_value = 1.0f },
};
g_renderer* renderer = calloc(1, sizeof(g_renderer));
if(renderer != NULL) {
log_info("Renderer allocated successfully");
log_debug("Renderer pointer: %p", renderer);
renderer->pass_action = (sg_pass_action){
.colors = { color_action, color_action, color_action, color_action },
.depth = { .load_action = SG_LOADACTION_CLEAR, .clear_value = 1.0f },
};
} else {
log_fatal("Failed to allocate renderer");
exit(EXIT_FAILURE);
}
return renderer;
}

View file

@ -0,0 +1,8 @@
#include <gear/graphics/renderer.h>
#include <log.c/log.h>
void g_renderer_destroy(g_renderer* renderer) {
free(renderer);
log_debug("Freed renderer: %p", renderer);
}

View file

@ -0,0 +1,19 @@
#include <gear/graphics/pipeline.h>
sg_pipeline g_pipeline_create(sg_shader shader, sg_vertex_layout_state layout) {
return sg_make_pipeline(&(sg_pipeline_desc){
.shader = shader,
.layout = layout,
.index_type = SG_INDEXTYPE_UINT32,
.cull_mode = SG_CULLMODE_BACK,
.depth = {
.compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true,
},
});
}
void g_pipeline_bind(g_renderer* renderer, sg_pipeline pipeline) {
sg_apply_pipeline(pipeline);
renderer->bound_pipeline_id = pipeline.id;
}

View file

@ -0,0 +1,22 @@
#include <gear/graphics/renderer.h>
#include <gear/graphics/pipeline.h>
#include <sokol/sokol_glue.h>
void g_renderer_begin(g_renderer* renderer) {
sg_begin_pass(&(sg_pass){ .action = renderer->pass_action, .swapchain = sglue_swapchain() });
}
void g_renderer_draw(g_renderer* renderer, g_renderer_object object, u32 elements) {
if(renderer->bound_pipeline_id != object.pipeline.id) {
g_pipeline_bind(renderer, object.pipeline);
sg_apply_bindings(&object.bind);
}
sg_draw(0, elements, 1);
};
void g_renderer_end(g_renderer* renderer) {
sg_end_pass();
sg_commit();
renderer->bound_pipeline_id = 0;
}

View file

@ -1,7 +1,12 @@
#include <gear/textures.h>
#include <gear/graphics/textures.h>
#include <gear/images.h>
#include <log.c/log.h>
g_texture* g_texture_create(g_image* image) {
return g_texture_create_filtered(image, SG_FILTER_LINEAR, SG_FILTER_LINEAR);
}
g_texture* g_texture_create_filtered(g_image* image, sg_filter min_filter, sg_filter mag_filter) {
sg_image sg_img = sg_make_image(&(sg_image_desc){
.width = image->width,
.height = image->height,
@ -12,18 +17,26 @@ g_texture* g_texture_create(g_image* image) {
.pixel_format = SG_PIXELFORMAT_RGBA8 // has to be used for opengl support
});
g_image_free(image);
sg_sampler sg_samp = sg_make_sampler(&(sg_sampler_desc){
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR
.min_filter = min_filter,
.mag_filter = mag_filter
});
g_texture* texture = calloc(1, sizeof(g_texture));
if(texture != NULL) {
log_info("Texture allocated successfully");
log_debug("Texture pointer: %p", texture);
texture->width = image->width;
texture->height = image->height;
texture->image = sg_img;
texture->sampler = sg_samp;
} else {
log_fatal("Failed to allocate texture");
exit(EXIT_FAILURE);
}
g_image_destroy(image);
return texture;
}

View file

@ -0,0 +1,8 @@
#include <gear/graphics/textures.h>
#include <log.c/log.h>
void g_texture_destroy(g_texture* texture) {
free(texture);
log_debug("Freed texture: %p", texture);
}

View file

@ -1,13 +1,20 @@
#include <gear/images.h>
#include <string.h>
#include <log.c/log.h>
g_image* g_image_create(u8* pixels, i32 width, i32 height) {
g_image* p_image = calloc(1, sizeof(g_image));
if (p_image != NULL) {
log_info("Image allocated successfully");
log_debug("Image pointer: %p", p_image);
p_image->width = width;
p_image->height = height;
p_image->channels = G_IMAGE_CHANNELS;
p_image->pixels = pixels;
} else {
log_fatal("Failed to allocate image");
exit(EXIT_FAILURE);
}
return p_image;

View file

@ -1,7 +1,10 @@
#include <gear/images.h>
#include <stb/stb_image.h>
#include <log.c/log.h>
void g_image_free(g_image* image) {
void g_image_destroy(g_image* image) {
stbi_image_free(image->pixels);
free(image);
log_debug("Freed image: %p", image);
}

View file

@ -1,116 +1,105 @@
#include "gear/images.h"
#include <gear/textures.h>
#include <gear/graphics/renderer.h>
#include <gear/camera.h>
#include <gear/ui/gui.h>
#include <gear/ui/console.h>
#include <sokol/sokol_app.h>
#include <sokol/sokol_gfx.h>
#include <sokol/sokol_log.h>
#include <sokol/sokol_glue.h>
#include <slibs/slibs.h>
#include <HandmadeMath/HandmadeMath.h>
#include <shaders/transform.glsl.h>
#include <log.c/log.h>
g_renderer* renderer;
g_camera* camera;
g_gui* gui;
struct nk_font* font;
typedef struct {
float x, y, z;
uint32_t color;
int16_t u, v;
} vertex_t;
static void init(void) {
void init() {
sg_setup(&(sg_desc){
.environment = sglue_environment(),
.logger.func = slog_func,
});
log_info("Sokol graphics initialized successfully");
vertex_t vertices[] = {
{ 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 1.0f * 32767, 1.0f * 32767 }, // top right
{ 1.0f, -1.0f, 0.0f, 0xFFFFFFFF, 1.0f * 32767, 0.0f * 32767 }, // bottom right
{ -1.0f, -1.0f, 0.0f, 0xFFFFFFFF, 0.0f * 32767, 0.0f * 32767 }, // bottom left
{ -1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0.0f * 32767, 1.0f * 32767 } // top left
};
uint16_t indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
sg_bindings* bind = calloc(1, sizeof(sg_bindings));
sl_vec_push(state.bindings, bind);
bind->vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.data = SG_RANGE(vertices),
});
bind->index_buffer = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_INDEXBUFFER,
.data = SG_RANGE(indices),
});
g_texture* texture = g_texture_create(g_image_load("happi.jpg"));
bind->fs.images[SLOT_tex] = texture->image;
bind->fs.samplers[SLOT_smp] = texture->sampler;
sg_shader shd = sg_make_shader(transform_shader_desc(sg_query_backend()));
state.pip = sg_make_pipeline(&(sg_pipeline_desc){
.shader = shd,
.layout = {
.attrs = {
[ATTR_vs_pos].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_vs_color0].format = SG_VERTEXFORMAT_UBYTE4N,
[ATTR_vs_texcoord0].format = SG_VERTEXFORMAT_SHORT2N,
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_BACK,
.depth = {
.compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true,
},
});
}
float t = 0.0f;
void frame(void) {
t += sapp_frame_duration();
sg_begin_pass(&(sg_pass){ .action = state.pass_action, .swapchain = sglue_swapchain() });
sg_apply_pipeline(state.pip);
HMM_Mat4 view = HMM_Translate(HMM_V3(0.0f, 0.0f, -3.0f));
HMM_Mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(45.0f), sapp_widthf() / sapp_heightf(), 0.1f, 100.0f);
HMM_Mat4 view_proj = HMM_Mul(projection, view);
for(size_t i = 0; i < state.bindings.size; i++) {
HMM_Mat4 model = HMM_Rotate_RH(HMM_AngleDeg(-55.0f), HMM_V3(1.0f, 0.0f, 0.0f));
model = HMM_Mul(model, HMM_Rotate_RH(HMM_AngleDeg(sin(t * 2) * 10), HMM_V3(0.0f, 0.2f, 0.0f)));
HMM_Mat4 mvp = HMM_Mul(view_proj, model);
vs_params_t params = {
.mvp = mvp,
.texture_scale = HMM_V2(1.0f, 1.0f),
};
sg_apply_bindings(state.bindings.data[i]);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, SG_RANGE_REF(params));
sg_draw(0, 6, 1);
renderer = g_renderer_create(G_CYAN);
gui = g_gui_create();
camera = g_camera_create(HMM_V3(0.0f, 0.0f, -3.0f), HMM_V3(0.0f, 0.0f, 0.0f), 70.0f);
log_info("GUI Layers (%d):", gui->layers.size);
for(sl_vec_it(layer, gui->layers)) {
log_info(" %s", (*layer)->name);
}
sg_end_pass();
sg_commit();
struct nk_font_atlas* atlas = calloc(1, sizeof(struct nk_font_atlas));
nk_font_atlas_init_default(atlas);
nk_font_atlas_begin(atlas);
float font_size = 22.0f;
const char* font_path = "assets/OpenSans-Regular.ttf";
struct nk_font_config config = nk_font_config(font_size);
font = nk_font_atlas_add_from_file(atlas, font_path, font_size, &config);
const void *image;
int atlas_width, atlas_height;
image = nk_font_atlas_bake(atlas, &atlas_width, &atlas_height, NK_FONT_ATLAS_RGBA32);
sg_image_desc img_desc = {0};
img_desc.width = atlas_width;
img_desc.height = atlas_height;
img_desc.data.subimage[0][0].ptr = image;
img_desc.data.subimage[0][0].size = atlas_width * atlas_height * 4;
img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
sg_image font_image = sg_make_image(&img_desc);
sg_sampler samp = sg_make_sampler(&(sg_sampler_desc){ 0 });
snk_image_t snk_img = snk_make_image(&(snk_image_desc_t){
.image = font_image,
.sampler = samp
});
// Complete the font atlas setup
nk_font_atlas_end(atlas, snk_nkhandle(snk_img), NULL);
}
void cleanup(void) {
void frame() {
g_gui_update(gui);
nk_style_set_font(gui->ctx, &font->handle);
g_renderer_begin(renderer);
g_gui_render(sapp_width(), sapp_height());
g_renderer_end(renderer);
}
void cleanup() {
g_renderer_destroy(renderer);
g_gui_destroy(gui);
g_camera_destroy(camera);
sg_shutdown();
}
void input(const sapp_event* event) {
snk_handle_event(event);
}
sapp_desc sokol_main(int argc, char* argv[]) {
(void)argc; (void)argv;
FILE* log_fd = fopen("log.txt", "w");
log_add_fp(log_fd, LOG_TRACE);
log_info("Command line arguments (%d):", argc);
for(i32 i = 0; i < argc; i++) {
log_info(" %s", argv[i]);
}
return (sapp_desc){
.init_cb = init,
.frame_cb = frame,
.cleanup_cb = cleanup,
.event_cb = input,
.width = 640,
.height = 480,
.window_title = "Gear",

91
src/old.c Normal file
View file

@ -0,0 +1,91 @@
/*#include "gear/camera.h"
#include "gear/graphics/color.h"
#include "gear/graphics/models.h"
#include <gear/images.h>
#include <gear/graphics/textures.h>
#include <gear/graphics/renderer.h>
#include <gear/graphics/pipeline.h>
#include <sokol/sokol_app.h>
#include <sokol/sokol_gfx.h>
#include <sokol/sokol_log.h>
#include <sokol/sokol_glue.h>
#include <slibs/slibs.h>
#include <HandmadeMath/HandmadeMath.h>
#include <shaders/transform.glsl.h>
g_renderer* renderer;
g_camera* camera;
g_model* cube;
g_renderer_object obj;
static void init(void) {
sg_setup(&(sg_desc){
.environment = sglue_environment(),
.logger.func = slog_func,
});
renderer = g_renderer_create(G_CYAN);
camera = g_camera_create(HMM_V3(0.0f, 0.0f, -5.0f), HMM_V3(0.0f, 0.0f, 0.0f), 45.0f);
obj.bind.vertex_buffers[0] = cube->vertex_buffer;
obj.bind.index_buffer = cube->index_buffer;
g_texture* texture = g_texture_create_filtered(g_image_load("happi.jpg"), SG_FILTER_NEAREST, SG_FILTER_NEAREST);
obj.bind.fs.images[SLOT_tex] = texture->image;
obj.bind.fs.samplers[SLOT_smp] = texture->sampler;
sg_shader shd = sg_make_shader(transform_shader_desc(sg_query_backend()));
obj.pipeline = g_pipeline_create(shd, (sg_vertex_layout_state){
.attrs = {
[ATTR_vs_pos].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_vs_color0].format = SG_VERTEXFORMAT_UBYTE4N,
[ATTR_vs_texcoord0].format = SG_VERTEXFORMAT_SHORT2N,
}
});
}
float t = 0.0f;
void frame(void) {
t += sapp_frame_duration();
mat4 view_proj = g_camera_matrix(camera);
g_renderer_begin(renderer);
mat4 model = HMM_Rotate_RH(HMM_AngleDeg(0.0f), HMM_V3(1.0f, 0.0f, 0.0f));
model = HMM_Mul(model, HMM_Rotate_RH(HMM_AngleDeg(t * 10), HMM_V3(0.0f, 1.0f, 0.0f)));
mat4 mvp = HMM_Mul(view_proj, model);
vs_params_t params = {
.mvp = mvp,
.texture_scale = HMM_V2(1.0f, 1.0f),
};
g_pipeline_bind(renderer, obj.pipeline);
sg_apply_bindings(&obj.bind);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, SG_RANGE_REF(params));
g_renderer_draw(renderer, obj, cube->indices.size);
g_renderer_end(renderer);
}
void cleanup(void) {
sg_shutdown();
}
sapp_desc sokol_main(int argc, char* argv[]) {
(void)argc; (void)argv;
return (sapp_desc){
.init_cb = init,
.frame_cb = frame,
.cleanup_cb = cleanup,
.width = 640,
.height = 480,
.window_title = "Gear",
.icon.sokol_default = true,
.logger.func = slog_func,
.swap_interval = 0
};
}*/

20
src/thirdparty/log.c/LICENSE vendored Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2020 rxi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

171
src/thirdparty/log.c/log.c vendored Normal file
View file

@ -0,0 +1,171 @@
#define LOG_USE_COLOR
/*
* Copyright (c) 2020 rxi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <log.c/log.h>
#define MAX_CALLBACKS 32
typedef struct {
log_LogFn fn;
void *udata;
int level;
} Callback;
static struct {
void *udata;
log_LockFn lock;
int level;
bool quiet;
Callback callbacks[MAX_CALLBACKS];
} L;
static const char *level_strings[] = {
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};
#ifdef LOG_USE_COLOR
static const char *level_colors[] = {
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"
};
#endif
static void stdout_callback(log_Event *ev) {
char buf[16];
buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
#ifdef LOG_USE_COLOR
fprintf(
ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
buf, level_colors[ev->level], level_strings[ev->level],
ev->file, ev->line);
#else
fprintf(
ev->udata, "%s %-5s %s:%d: ",
buf, level_strings[ev->level], ev->file, ev->line);
#endif
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "\n");
fflush(ev->udata);
}
static void file_callback(log_Event *ev) {
char buf[64];
buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
fprintf(
ev->udata, "%s %-5s %s:%d: ",
buf, level_strings[ev->level], ev->file, ev->line);
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "\n");
fflush(ev->udata);
}
static void lock(void) {
if (L.lock) { L.lock(true, L.udata); }
}
static void unlock(void) {
if (L.lock) { L.lock(false, L.udata); }
}
const char* log_level_string(int level) {
return level_strings[level];
}
void log_set_lock(log_LockFn fn, void *udata) {
L.lock = fn;
L.udata = udata;
}
void log_set_level(int level) {
L.level = level;
}
void log_set_quiet(bool enable) {
L.quiet = enable;
}
int log_add_callback(log_LogFn fn, void *udata, int level) {
for (int i = 0; i < MAX_CALLBACKS; i++) {
if (!L.callbacks[i].fn) {
L.callbacks[i] = (Callback) { fn, udata, level };
return 0;
}
}
return -1;
}
int log_add_fp(FILE *fp, int level) {
return log_add_callback(file_callback, fp, level);
}
static void init_event(log_Event *ev, void *udata) {
if (!ev->time) {
time_t t = time(NULL);
ev->time = localtime(&t);
}
ev->udata = udata;
}
void log_log(int level, const char *file, int line, const char *fmt, ...) {
log_Event ev = {
.fmt = fmt,
.file = file,
.line = line,
.level = level,
};
lock();
if (!L.quiet && level >= L.level) {
init_event(&ev, stderr);
va_start(ev.ap, fmt);
stdout_callback(&ev);
va_end(ev.ap);
}
for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) {
Callback *cb = &L.callbacks[i];
if (level >= cb->level) {
init_event(&ev, cb->udata);
va_start(ev.ap, fmt);
cb->fn(&ev);
va_end(ev.ap);
}
}
unlock();
}

2
src/thirdparty/nuklear/nuklear.c vendored Normal file
View file

@ -0,0 +1,2 @@
#define NK_IMPLEMENTATION
#include <nuklear/nuklear_defines.h>

2
src/thirdparty/slibs/slibs.c vendored Normal file
View file

@ -0,0 +1,2 @@
#define SL_IMPLEMENTATION
#include <slibs/slibs.h>

View file

@ -7,4 +7,4 @@
#include <sokol/sokol_glue.h>
#include <sokol/sokol_log.h>
#include <sokol/sokol_time.h>
#endif
#endif

View file

@ -1,3 +1,12 @@
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_STANDARD_VARARGS
#include <nuklear/nuklear.h>
#ifdef SOKOL_METAL
#define SOKOL_IMPL
#include <sokol/sokol_app.h>

2
src/thirdparty/sokol/sokol_nuklear.c vendored Normal file
View file

@ -0,0 +1,2 @@
#define SOKOL_NUKLEAR_IMPL
#include <gear/ui/gui.h>

53
src/ui/console/create.c Normal file
View file

@ -0,0 +1,53 @@
#include "log.c/log.h"
#include <gear/ui/gui.h>
#include <gear/ui/console.h>
void log_callback(log_Event* event) {
char* formatted_input;
vasprintf(&formatted_input, event->fmt, event->ap);
char* formatted;
sz len = asprintf(&formatted, "%s\n", formatted_input);
free(formatted_input);
g_console* console = event->udata;
for(sz i = 0; i < len; i++) {
sl_vec_push(console->output, formatted[i]);
}
free(formatted);
}
g_gui_layer* g_console_create() {
g_console* console = calloc(1, sizeof(g_console));
if(console != NULL) {
log_info("Console allocated successfully");
log_debug("Console pointer: %p", console);
console->input = (sl_string){
.data = malloc(1),
.size = 0,
.capacity = 1
};
console->output = (sl_string){
.data = malloc(1),
.size = 0,
.capacity = 1
};
} else {
log_fatal("Failed to allocate console");
exit(EXIT_FAILURE);
}
log_add_callback(log_callback, console, LOG_INFO);
g_gui_layer* layer = calloc(1, sizeof(g_gui_layer));
layer->name = "Console";
layer->draw = g_console_draw;
layer->data = console;
return layer;
}

12
src/ui/console/destroy.c Normal file
View file

@ -0,0 +1,12 @@
#include <gear/ui/console.h>
#include <log.c/log.h>
void g_console_destroy(void* console_vp) {
g_console* console = console_vp;
sl_vec_free(console->input);
sl_vec_free(console->output);
free(console);
log_debug("Freed console: %p", console);
}

35
src/ui/console/draw.c Normal file
View file

@ -0,0 +1,35 @@
#include <gear/ui/console.h>
#include <gear/ui/gui.h>
void g_console_draw(g_gui_context* ctx, g_gui_layer* layer) {
g_console* console = layer->data;
if(console->input.size >= console->input.capacity) {
sl_vec_grow(console->input);
}
if(console->output.size >= console->output.capacity) {
sl_vec_grow(console->input);
}
if (nk_begin(ctx, "Console", nk_rect(50, 50, 500, 500),
NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_CLOSABLE | NK_WINDOW_SCALABLE)) {
float frame_height = nk_window_get_content_region(ctx).h;
nk_layout_row_dynamic(ctx, frame_height - 42.5f, 1);
snk_edit_string(ctx, NK_EDIT_CLIPBOARD | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE,
console->output.data, (i32*)(&console->output.size),
console->output.size + 1, nk_filter_default);
nk_layout_row_dynamic(ctx, 30.0f, 1);
enum nk_edit_events event = snk_edit_string(ctx, NK_EDIT_FIELD | NK_EDIT_SIG_ENTER,
console->input.data, (i32*)(&console->input.size),
console->input.size + 2, nk_filter_default);
if(event & NK_EDIT_COMMITED) {
log_info("cmd: %s", sl_c_str(console->input));
console->input.size = 0;
}
}
nk_end(ctx);
}

25
src/ui/gui/create.c Normal file
View file

@ -0,0 +1,25 @@
#include <gear/ui/gui.h>
#include <gear/ui/console.h>
#include <sokol/sokol_log.h>
#include <log.c/log.h>
g_gui* g_gui_create() {
snk_setup(&(snk_desc_t){
.dpi_scale = sapp_dpi_scale(),
.logger.func = slog_func,
});
log_info("Sokol nuklear initialized successfully");
g_gui* gui = calloc(1, sizeof(g_gui));
if(gui != NULL) {
log_info("GUI allocated successfully");
log_debug("GUI pointer: %p", gui);
g_gui_add_layer(&gui->layers, g_console_create, g_console_destroy);
} else {
log_fatal("Failed to allocate GUI");
exit(EXIT_FAILURE);
}
return gui;
}

15
src/ui/gui/destroy.c Normal file
View file

@ -0,0 +1,15 @@
#include <gear/ui/gui.h>
#include <log.c/log.h>
void g_gui_destroy(g_gui* gui) {
for(sl_vec_it(layer, gui->layers)) {
log_debug("Freeing layer %s", (*layer)->name);
(*layer)->destroy((*layer)->data);
log_debug("Freed layer");
}
sl_vec_free(gui->layers);
free(gui);
log_debug("Freed GUI: %p", gui);
}

8
src/ui/gui/layers.c Normal file
View file

@ -0,0 +1,8 @@
#include <gear/ui/gui.h>
void g_gui_add_layer(g_gui_layers* layers, g_gui_layer_create_function create_function, g_gui_layer_destroy_function destroy_function) {
g_gui_layer* layer = create_function();
layer->destroy = destroy_function;
sl_vec_push(*layers, layer);
}

5
src/ui/gui/render.c Normal file
View file

@ -0,0 +1,5 @@
#include <gear/ui/gui.h>
void g_gui_render(i32 width, i32 height) {
snk_render(width, height);
}

13
src/ui/gui/update.c Normal file
View file

@ -0,0 +1,13 @@
#include <gear/ui/gui.h>
#include <sokol/sokol_gfx.h>
#include <sokol/sokol_app.h>
#include <sokol/util/sokol_nuklear.h>
#include <log.c/log.h>
void g_gui_update(g_gui* gui) {
gui->ctx = snk_new_frame();
for(sl_vec_it(layer, gui->layers)) {
(*layer)->draw(gui->ctx, *layer);
}
}