Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/render.h
2025-09-02 14:43:36 +02:00

552 lines
20 KiB
C

/*
void gfx_calc_mono(fchar_t *glyphs, int width, int height) {
fchar_t *ch;
for(int z = 0; z < 256; z++) {
ch = &glyphs[z];
if(ch->u) {
ch->s = ch->t = 2;
ch->u = width - 2;
ch->v = height - 2;
}
}
}
*/
byte gfx_font_special(int width, uint ch) {
return ((ch == CHR_UNK) || (ch == CHR_WSPC)) ? width : ((ch == CHR_SPC) ? (width / 6) : 255);
}
void gfx_calc_font(byte *data, fchar_t *glyphs, int width, int height, int page) {
int off;
fchar_t *ch;
for(int z = 0; z < 256; z++) {
ch = &glyphs[z];
if((ch->u = gfx_font_special(width, (page << 8) + z)) != 255) {
ch->s = ch->t = 0;
ch->v = ((int)ch->u) * height / width;
if(((page << 8) + z) != CHR_UNK) {
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
off = FONT_STRIDE(x, y, z);
data[off+3] = 0;
}
}
}
continue;
}
ch->s = ch->t = 255;
ch->u = ch->v = 0;
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
off = FONT_STRIDE(x, y, z);
if(data[off+3]) {
ch->s = x < ch->s ? x : ch->s;
ch->t = y < ch->t ? y : ch->t;
ch->u = x > ch->u ? x : ch->u;
ch->v = y > ch->v ? y : ch->v;
}
}
}
if(ch->s == 255 && ch->t == 255 && ch->u == 0 && ch->v == 0) {
ch->s = ch->t = 0;
}
else {
ch->u += 1;
ch->v += 1;
}
}
}
int gfx_load_font(font_t *font, const char *path) {
byte *data;
int width, height;
int pages = 0;
font->xglyph = 0;
// if(mono)
// mono->xglyph = 0;
for(int page = 0; page < UNI_MAX_PAGES; page++) {
sprintf(sys.work_buf, "fonts/%s_%04x.png", path, page);
if(!(data = img_load(sys.work_buf, &width, &height, 0, 1))) {
if(!page) {
return 0;
}
font->textures[page] = 0;
font->sizes[page] = NULL;
// if(mono) {
// mono->textures[page] = 0;
// mono->sizes[page] = NULL;
// }
continue;
}
if(page == 0) {
if(width > 3968 || height > 3968) {
mem_free(data);
return 0;
}
else if((width % 16) || (height % 16)) {
mem_free(data);
return 0;
}
font->xsize = width;
font->ysize = height;
font->xglyph = width >> 4;
font->yglyph = height >> 4;
}
else if(font->xsize != width || font->ysize != height) {
font->textures[page] = 0;
font->sizes[page] = NULL;
// if(mono) {
// mono->textures[page] = 0;
// mono->sizes[page] = NULL;
// }
mem_free(data);
continue;
}
pages += 1;
font->sizes[page] = mem_alloc(256 * sizeof(fchar_t), MEM_FONT);
gfx_calc_font(data, font->sizes[page], font->xglyph, font->yglyph, page);
tex_push(&font->textures[page], data, width, height);
// if(mono) {
// mono->sizes[page] = mem_alloc(256 * sizeof(fchar_t), MEM_FONT);
// memcpy(mono->sizes[page], font->sizes[page], 256 * sizeof(fchar_t));
// gfx_calc_mono(mono->sizes[page], font->xglyph, font->yglyph);
// mono->textures[page] = font->textures[page];
// }
logd(LOG_GFX, STR_TEX_ILOADED, sys.work_buf, font->textures[page]);
mem_free(data);
}
// if(mono) {
// mono->xsize = font->xsize;
// mono->ysize = font->ysize;
// mono->xglyph = font->xglyph;
// mono->yglyph = font->yglyph;
// }
return pages;
}
/*
int gfx_load_font_int(font_t *font, const byte **fdata, const byte **fsizes) {
int pages = 0;
byte *data = mem_alloc(12 * 16 * 18 * 16 * 4, MEM_IMAGE);
font->xglyph = 12;
font->yglyph = 18;
font->xsize = 12 * 16;
font->ysize = 18 * 16;
for(int page = 0; page < UNI_MAX_PAGES; page++) {
sprintf(sys.work_buf, "font_%04x", page);
if(!fdata[page]) {
font->textures[page] = 0;
font->sizes[page] = NULL;
continue;
}
pages += 1;
font->sizes[page] = (fchar_t *)fsizes[page];
tex_unpack_1bit(data, fdata[page], 12 * 16 * 18 * 16);
tex_push(&font->textures[page], data, 12 * 16, 18 * 16);
// mono->sizes[page] = mem_alloc(256 * sizeof(fchar_t), MEM_FONT);
// memcpy(mono->sizes[page], fsizes[page], 256 * sizeof(fchar_t));
// gfx_calc_mono(mono->sizes[page], font->xglyph, font->yglyph);
// mono->textures[page] = font->textures[page];
logd(LOG_GFX, STR_TEX_ILOADED, sys.work_buf, font->textures[page]);
}
mem_free(data);
return pages;
}
*/
void gfx_free_font(font_t *font) {
for(int page = 0; (page < UNI_MAX_PAGES) && font->xglyph; page++) {
if(font->sizes[page]) {
mem_free(font->sizes[page]);
tex_delete(&font->textures[page]);
}
// if(mono && mono->sizes[page])
// mem_free(mono->sizes[page]);
}
}
/*
void gfx_free_font_int(font_t *font) {
for(int page = 0; page < UNI_MAX_PAGES; page++) {
if(font->sizes[page])
tex_delete(&font->textures[page]);
// if(mono->sizes[page])
// mem_free(mono->sizes[page]);
}
}
*/
void gfx_aux_colors(const uint *colors) {
memcpy(gdr.aux_colors, colors, sizeof(uint) * 8);
}
void gfx_back_color(uint color) {
gdr.clear_r = (float)((uint)((color >> 16) & 0xff)) / 255.0f;
gdr.clear_g = (float)((uint)((color >> 8) & 0xff)) / 255.0f;
gdr.clear_b = (float)((uint)(color & 0xff)) / 255.0f;
gdr.clear_a = (float)((uint)((color >> 24) & 0xff)) / 255.0f;
}
void shd_fnc_tex() {
shd_int("tex", 0);
}
void shd_fnc_world() {
shd_int("tex", 0);
glUniformBlockBinding(gdr.shader, glGetUniformBlockIndex(gdr.shader, "light_block"), 0);
}
void gfx_view(camera_t *cam, mat4 mat, float x, float y, float z) {
vec3 pos;
vec3 center;
VEC3_SET(pos, x, y, z);
glm_vec3_add(pos, cam->front, center);
glm_mat4_identity(mat);
glm_lookat(pos, center, cam->up, mat);
}
void gfx_perspective(camera_t *cam, mat4 mat) {
glm_mat4_identity(mat);
glm_perspective(glm_rad(gdr.fov - (cam->zoom * (gdr.fov - 1.0f))), ((float)wcf.current->frame_x) / ((float)wcf.current->frame_y), gdr.clip_near, gdr.clip_far, mat);
}
void shd_pass_rect(void *u) {
// shd_sel(gdr.shd_rect);
shd_vec2v("screen", (float)wcf.current->fb_x, (float)wcf.current->fb_y);
glBindVertexArray(gdr.vao_quad);
glActiveTexture(GL_TEXTURE0);
}
void shd_pass_text(void *u) {
// shd_sel(gdr.shd_text);
shd_vec2v("screen", (float)wcf.current->fb_x, (float)wcf.current->fb_y);
shd_float("time", tmr_ftime());
glBindVertexArray(gdr.vao_quad);
glActiveTexture(GL_TEXTURE0);
}
void shd_pass_blit(void *u) {
// shd_sel(gdr.shd_blit);
glBindVertexArray(gdr.vao_quad);
glActiveTexture(GL_TEXTURE0);
}
void shd_pass_world(world_t *world) {
mat4 mat;
// shd_sel(gdr.shd_world);
shd_float("clip_near", gdr.clip_near);
shd_float("clip_far", gdr.clip_far);
shd_vec2v("screen", (float)wcf.current->frame_x, (float)wcf.current->frame_y);
// shd_vec3v("world_size", (float)(TEMP_LM_SIZE * CHUNK_SIZE), (float)(TEMP_LM_SIZE * CHUNK_SIZE), (float)(TEMP_LM_SIZE * CHUNK_SIZE));
shd_vec3v("cam_pos", world->camera.pos_x, world->camera.pos_y, world->camera.pos_z);
gfx_view(&world->camera, mat, world->camera.pos_x, world->camera.pos_y, world->camera.pos_z);
shd_mat4("view", mat);
gfx_perspective(&world->camera, mat);
shd_mat4("projection", mat);
/*
glm_mat4_identity(mat);
vec3 v;
VEC3_SET(v, 100.0f, 0.5f, 100.0f);
glm_scale(mat, v);
VEC3_SET(v, 0.0f, -1.0f, 0.0f);
glm_translate(mat, v);
shd_mat4("model", mat);
shd_scolor("specular", 0xffffff);
shd_float("shine", 4.0f);
*/
shd_vec3v("dir_direction", gdr.ambient_x, gdr.ambient_y, gdr.ambient_z);
// shd_vec3v("dir_ambient", 0.1f, 0.1f, 0.2f);
shd_vec3v("dir_ambient", gdr.clear_r, gdr.clear_g, gdr.clear_b);
shd_vec3v("dir_diffuse", gdr.clear_r * 1.25f, gdr.clear_g * 1.25f, gdr.clear_b * 1.25f);
shd_vec3v("dir_specular", gdr.clear_r * 1.5f, gdr.clear_g * 1.5f, gdr.clear_b * 1.5f);
shd_float("light_factor", gdr.light_blend);
shd_float("max_vert_dist", gdr.light_dist_vert);
shd_float("max_cam_dist", gdr.light_dist_cam);
// shd_float("time", tmr_ftime());
// glBindVertexArray(gdr.vao_box);
// glActiveTexture(GL_TEXTURE1);
// glBindTexture(GL_TEXTURE_2D, gdr.fbtex_lightmap);
shd_int("n_lights", world->s_lights);
glActiveTexture(GL_TEXTURE0);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, world->light_buf);
}
void shd_pass_vis(world_t *world) {
mat4 mat;
gfx_view(&world->camera, mat, world->camera.pos_x, world->camera.pos_y, world->camera.pos_z);
shd_mat4("view", mat);
gfx_perspective(&world->camera, mat);
shd_mat4("projection", mat);
}
void shd_pass_grid(world_t *world) {
mat4 mat;
// shd_sel(gdr.shd_vis);
shd_float("clip_near", gdr.clip_near);
shd_float("clip_far", gdr.clip_far);
shd_vec2v("screen", (float)wcf.current->frame_x, (float)wcf.current->frame_y);
gfx_view(&world->camera, mat, world->camera.pos_x, world->camera.pos_y, world->camera.pos_z);
shd_mat4("view", mat);
gfx_perspective(&world->camera, mat);
shd_mat4("projection", mat);
shd_float("time", tmr_ftime());
// glActiveTexture(GL_TEXTURE0);
}
byte gfx_init() {
gdr.aniso_max = 1.0f;
// if(gdr.aniso_avail = (GL_API_4_6 || gl_has_ext("GL_EXT_texture_filter_anisotropic") || gl_has_ext("GL_ARB_texture_filter_anisotropic")))
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &gdr.aniso_max);
tbl_init(&gdr.textures, 256, 64, sizeof(tex_t), MEM_DRAW);
tbl_init(&gdr.buffers, 1024, 16, sizeof(buf_t), MEM_DRAW);
tbl_init(&gdr.shaders, 1, 16, sizeof(shd_t), MEM_DRAW);
tbl_init(&gdr.framebufs, 1, 16, sizeof(fbo_t), MEM_DRAW);
tbl_init(&gdr.drawlists, 1, 16384, sizeof(drawlist_t), MEM_DRAW);
tbl_init(&gdr.materials, 16, 32, sizeof(material_t), MEM_DRAW);
shd_setvars();
LOAD_SHADER(text, shd_fnc_tex, shd_pass_text);
LOAD_SHADER(rect, shd_fnc_tex, shd_pass_rect);
LOAD_SHADER(blit, shd_fnc_tex, shd_pass_blit);
LOAD_SHADER(world, shd_fnc_world, shd_pass_world);
// LOAD_SHADER(lightmap, NULL, NULL);
LOAD_SHADER(vis, NULL, shd_pass_vis);
LOAD_SHADER(grid, NULL, shd_pass_grid);
sys.font_pages = gfx_load_font(&sys.font, "font");
buf_init_sys(&gdr.vbo_quad, &gdr.vao_quad, vert_quad, sizeof(vert_quad), 2, 2);
if(!fb_init_sys(&sys.console->fb_gui, &sys.console->fbtex_gui))
return 0;
tex_gen_fallback(&gdr.tex_fallback, 8);
gfx_aux_colors(aux_colors);
// gfx_back_color(0x000000);
// gfx_back_color(0xff20208f);
gfx_back_color(0xff000000);
// gui_style_default(&sys.style);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// gdr.buf_lightmap = buf_init(1, &gdr.vbo_lightmap, &gdr.vao_lightmap, NULL, 0, 2, 2);
// gdr.fbt_lightmap = fb_init(&gdr.fb_lightmap, &gdr.fbtex_lightmap, NULL, 0, 1);
// gfx_init_world();
return 1;
}
void gfx_end() {
tex_clear();
buf_clear();
shd_clear();
fb_clear();
gfx_free_font(&sys.font);
tex_delete(&gdr.tex_fallback);
buf_delete(&gdr.vbo_quad, &gdr.vao_quad);
// shd_delete(&gdr.shd_rect);
// shd_delete(&gdr.shd_text);
// shd_delete(&gdr.shd_blit);
// shd_clearall();
// fb_delete(&sys.console->fb_gui, &sys.console->fbtex_gui);
tbl_clear(&gdr.textures);
tbl_clear(&gdr.buffers);
tbl_clear(&gdr.shaders);
tbl_clear(&gdr.framebufs);
tbl_clear(&gdr.drawlists);
tbl_clear(&gdr.materials);
}
void gfx_blit(uint tex) {
shd_sel(gdr.shd_blit, NULL);
glBindTexture(GL_TEXTURE_2D, tex);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void gfx_draw_rect(int x, int y, int w, int h, int border, uint tex, uint top, uint bottom, uint b_top, uint b_bottom) {
shd_sel(gdr.shd_rect, NULL);
shd_vec2v("offset", (float)x, (float)y);
shd_vec2v("size", (float)w, (float)h);
shd_bool("use_tex", tex ? 1 : 0);
shd_float("border", (float)border);
shd_color("fill_t", top);
shd_color("fill_b", bottom);
shd_color("border_t", b_top);
shd_color("border_b", b_bottom);
if(tex) {
glBindTexture(GL_TEXTURE_2D, tex);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void gfx_draw_gui(window_t *win) {
int x1, y1, x2, y2;
gui_t *elem = win->selected;
if(elem && elem->r_dirty && elem->type == GUI_DROPDOWN_HANDLE && !(elem->visible)) {
glScissor(elem->pos_x, (win->fb_y - (elem->pos_y + elem->size_y)) < 0 ? 0 : (win->fb_y - (elem->pos_y + elem->size_y)), elem->size_x, elem->size_y);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
elem->r_dirty = elem->t_dirty = 0;
win->selected = NULL;
for(int z = 0; z < win->n_elems; z++) {
if((win->elems[z].pos_y + win->elems[z].size_y) > elem->pos_y && win->elems[z].pos_y < (elem->pos_y + elem->size_y) &&
(win->elems[z].pos_x + win->elems[z].size_x) > elem->pos_x && win->elems[z].pos_x < (elem->pos_x + elem->size_x) && win->elems[z].visible)
win->elems[z].r_dirty = 1;
}
}
for(int z = 0; z < win->n_elems; z++) {
elem = &win->elems[z];
if(elem->r_dirty || elem->t_dirty) {
if(win->selected == elem && elem->type == GUI_DROPDOWN_HANDLE && elem->visible)
continue;
glScissor(elem->pos_x, (win->fb_y - (elem->pos_y + elem->size_y)) < 0 ? 0 : (win->fb_y - (elem->pos_y + elem->size_y)), elem->size_x, elem->size_y);
// logd("DBG", "%d @ %d %d -> %d %d", elem->id, elem->pos_x, elem->pos_y, elem->pos_x + elem->size_x, elem->pos_y + elem->size_y);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
if(elem->type == GUI_CUSTOM)
elem->func(elem, 0);
glDisable(GL_SCISSOR_TEST);
if(elem->visible && (elem->type != GUI_CUSTOM))
gfx_draw_rect(elem->pos_x, elem->pos_y, elem->size_x, elem->size_y, elem->border, elem->texture, elem->color_fill_t, elem->color_fill_b, elem->color_brdr_t, elem->color_brdr_b);
if(elem->visible && (elem->type == GUI_SLIDER))
gfx_draw_rect(elem->pos_x + elem->sel_start - (elem->sel_end / 2), elem->pos_y, elem->sel_end, elem->size_y, elem->sel_drag, elem->texture, elem->margin_x1, elem->margin_y1, elem->margin_x2, elem->margin_y2);
elem->r_dirty = 0;
elem->t_dirty = elem->visible;
// logd("DBG", "@ r");
}
}
// gfx_pass_text();
for(int z = 0; z < win->n_elems; z++) {
elem = &win->elems[z];
if(elem->t_dirty && elem->visible) {
if(win->selected == elem && elem->type == GUI_DROPDOWN_HANDLE)
continue;
x1 = elem->pos_x + ((elem->type != GUI_SLIDER) ? elem->margin_x1 : 0);
y1 = elem->pos_y + ((elem->type != GUI_SLIDER) ? elem->margin_y1 : 0);
x2 = elem->size_x - ((elem->type != GUI_SLIDER) ? (elem->margin_x1 + elem->margin_x2) : 0);
y2 = elem->size_y - ((elem->type != GUI_SLIDER) ? (elem->margin_y1 + elem->margin_y2) : 0);
// if(elem->type == GUI_FIELD) {
glScissor(x1 < 0 ? 0 : x1, (win->fb_y - (y1 + y2)) < 0 ? 0 : (win->fb_y - (y1 + y2)), x2 < 0 ? 0 : x2, y2 < 0 ? 0 : y2);
glEnable(GL_SCISSOR_TEST);
// }
if(elem->type == GUI_CUSTOM)
elem->func(elem, 1);
else
elem->t_dirty = txt_draw(x1 + (elem->xbreak ? 0 : elem->text_x), y1 + elem->text_y,
0, elem->font_size * elem->font->yglyph,
elem->font_size * (elem->font->yglyph + elem->line_space), x1 + elem->text_x, y1 + elem->text_y,
elem->xbreak ? (elem->pos_x + x2) : 0x7fffffff, 0x7fffffff, elem->color_text, 0x00000000, elem->font, elem->text);
if(elem->type == GUI_FIELD && elem->sel_start >= 0 && elem->sel_end != elem->sel_start)
txt_draw_range(elem->sel_start, elem->sel_end, x1 + (elem->xbreak ? 0 : elem->text_x), y1 + elem->text_y, 0, elem->font_size * elem->font->yglyph,
elem->font_size * elem->font->yglyph, x1 + elem->text_x, y1 + elem->text_y,
elem->xbreak ? (elem->pos_x + x2) : 0x7fffffff, 0x7fffffff, 0x00000000, sys.style.select, elem->font, elem->text);
// logd("DBG", "%d @ %d %d -> %d %d", elem->id, x1, y1, elem->pos_x + x2, elem->pos_y + y2);
// if(elem->type == GUI_FIELD) {
glDisable(GL_SCISSOR_TEST);
// glScissor(0, 0, sys.fb_x, sys.fb_y);
// }
}
}
elem = win->selected;
if(elem && (elem->r_dirty || elem->t_dirty) && elem->type == GUI_DROPDOWN_HANDLE && elem->visible) {
// gfx_pass_rect();
glScissor(elem->pos_x, (win->fb_y - (elem->pos_y + elem->size_y)) < 0 ? 0 : (win->fb_y - (elem->pos_y + elem->size_y)), elem->size_x, elem->size_y);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
gfx_draw_rect(elem->pos_x, elem->pos_y, elem->size_x, elem->size_y, elem->border, elem->texture, elem->color_fill_t, elem->color_fill_b, elem->color_brdr_t, elem->color_brdr_b);
elem->r_dirty = 0;
// gfx_pass_text();
x1 = elem->pos_x + elem->margin_x1;
y1 = elem->pos_y + elem->margin_y1;
x2 = elem->size_x - (elem->margin_x1 + elem->margin_x2);
y2 = elem->size_y - (elem->margin_y1 + elem->margin_y2);
glScissor(x1 < 0 ? 0 : x1, (win->fb_y - (y1 + y2)) < 0 ? 0 : (win->fb_y - (y1 + y2)), x2 < 0 ? 0 : x2, y2 < 0 ? 0 : y2);
glEnable(GL_SCISSOR_TEST);
elem->t_dirty = txt_draw(x1 + elem->text_x, y1 + elem->text_y,
0, elem->font_size * elem->font->yglyph,
elem->font_size * (elem->font->yglyph + elem->line_space), x1 + elem->text_x, y1 + elem->text_y,
0x7fffffff, 0x7fffffff, elem->color_text, 0x00000000, elem->font, elem->text);
glDisable(GL_SCISSOR_TEST);
}
}
byte gui_inside(gui_t *elem, int x, int y);
gui_t *gui_clicked(window_t *win, int x, int y);
void gfx_draw_gui_overlay(window_t *win) {
gui_t *elem;
if(win->open) {
elem = win->selected;
if(win->mouse && elem && elem->enabled && elem->visible && (elem->type != GUI_LABEL) && (elem->type != GUI_FIELD) && (elem->type != GUI_DROPDOWN_HANDLE) && (elem->type != GUI_CUSTOM)) {
gfx_draw_rect(elem->pos_x, elem->pos_y, elem->size_x, elem->size_y, 0, 0, sys.style.press_top, sys.style.press_btm, 0x00000000, 0x00000000);
return;
}
else if(elem && elem->enabled && elem->visible && (elem->type == GUI_FIELD)) {
if(elem->value && elem->sel_start >= 0 && elem->sel_end == elem->sel_start && fmodf(tmr_ftime(), 1.0f) < 0.5f) {
int x1 = elem->pos_x + elem->margin_x1;
int y1 = elem->pos_y + elem->margin_y1;
int x2 = elem->size_x - (elem->margin_x1 + elem->margin_x2);
int y2 = elem->size_y - (elem->margin_y1 + elem->margin_y2);
glScissor(x1 < 0 ? 0 : x1, (win->fb_y - (y1 + y2)) < 0 ? 0 : (win->fb_y - (y1 + y2)), x2 < 0 ? 0 : x2, y2 < 0 ? 0 : y2);
glEnable(GL_SCISSOR_TEST);
gfx_draw_rect(elem->min, elem->max, elem->font_size, elem->font->yglyph * elem->font_size, 0, 0, sys.style.cursor, sys.style.cursor, 0x00000000, 0x00000000);
glDisable(GL_SCISSOR_TEST);
}
}
elem = gui_clicked(win, win->mouse_x, win->mouse_y);
if(elem && elem->enabled && elem->visible && (elem->type != GUI_LABEL) && /* ( */ (elem->type != GUI_FIELD) && (elem->type != GUI_CUSTOM) /* || (elem != gui.selected)) */ ) {
if(elem->type == GUI_DROPDOWN_HANDLE) {
int m = ((win->mouse_y - (elem->pos_y + elem->margin_y1)) * elem->max / (elem->size_y - (elem->margin_y1 + elem->margin_y2)));
// if((sys.mouse_y - elem->pos_y) < (elem->size_y - elem->margin_y2))
gfx_draw_rect(elem->pos_x + elem->margin_x1, elem->pos_y + elem->margin_y1 + CLAMP_VALUE(m, 0, elem->max - 1) * ((elem->size_y - (elem->margin_y1 + elem->margin_y2)) / elem->max),
elem->size_x - (elem->margin_x1 + elem->margin_x2),
(elem->size_y - (elem->margin_y1 + elem->margin_y2)) / elem->max, 0, 0, sys.style.hover_top, sys.style.hover_btm, 0x00000000, 0x00000000);
}
else {
gfx_draw_rect(elem->pos_x, elem->pos_y, elem->size_x, elem->size_y, 0, 0, sys.style.hover_top, sys.style.hover_btm, 0x00000000, 0x00000000);
}
}
}
}
void gfx_draw_con_overlay(window_t *win) {
if(sys.hud_size) {
conmsg_t *con;
ulong fade = 1000ULL * (ulong)(sys.hud_fadeout);
font_t *font = &sys.font;
int y = sys.hud_bottom ? (win->frame_y - font->yglyph) : 0;
int pos = sys.hud_pos;
for(int z = 0; z < sys.hud_size; z++) {
if(--pos < 0)
pos = sys.hud_size - 1;
con = &sys.hud_msgs[pos];
if(con->message && (con->window == win)) {
if((sys.tmr_current - con->time) <= fade) {
txt_draw_range(0, con->length, win->offset_x, win->offset_y + y, 0, font->yglyph, font->yglyph,
win->offset_x, win->offset_y + y,
win->offset_x + win->frame_x, win->offset_y + win->frame_y,
0xffffffff, (uint)sys.hud_opacity << 24, font, con->message);
y += sys.hud_bottom ? -(font->yglyph) : font->yglyph;
}
else {
con->message = NULL;
}
}
}
}
}
material_t *gfx_add_material(uint texture, float density, uint spec_color, float shine, shd_t *shader) {
material_t *mat = tbl_push(&gdr.materials);
mat->texture = texture;
mat->density = density;
mat->spec_color = spec_color;
mat->shine = shine;
mat->shader = shader;
return mat;
}
void gfx_clear_materials() {
tbl_clear(&gdr.materials);
}