Primitive pak loader

This commit is contained in:
2025-07-20 23:16:30 +02:00
parent 7168bb8f1f
commit 0137186582
22 changed files with 508 additions and 411 deletions
+51
View File
@@ -0,0 +1,51 @@
[Metadata]
id=base
name=Wschód
# In this section, all the programs (commonly called "shaders") are
# loaded. These can be referenced from Guile. In this instance, since
# it's a base game package, they are also referenced in the C
# code. Modifying this can fuck up your game big time, so do a backup.
[Programs]
default=res/shaders/default.vert;res/shaders/default.frag
chunk=res/shaders/chunk.vert;res/shaders/chunk.frag
clouds=res/shaders/clouds.vert;res/shaders/clouds.frag
uiwidget=res/shaders/uiwidget.vert;res/shaders/uiwidget.frag
uitext=res/shaders/uitext.vert;res/shaders/uitext.frag
uidummy=res/shaders/uidummy.vert;res/shaders/uidummy.frag
# In this section we load textures. I think a lot of formats should be
# supported, but RGBA PNG is what I use. All of these can be
# referenced from Guile, and some of these are referenced in C (all
# the terrains, font0 and icons).
[Textures]
font0=res/textures/font_9x20.png
icons=res/textures/icons.png
terrain0=res/textures/dirt.png
terrain1=res/textures/drygrass.png
terrain2=res/textures/grass.png
terrain3=res/textures/rock_cement.png
terrain4=res/textures/asphalt_gravel.png
tree0=res/textures/tree.png
grass0=res/textures/grass0.png
clouds=res/textures/clouds.png
# The heightmap converts white (the highest) and black (the lowest)
# and everything inbetween into floating point values. The texturemap
# just uses all the RGBA channels as texture info (R=1, texture1, G=1,
# texture2, all 0, texture0, &c.). The entity map should base its
# colors on the colors defined in entity_templates.scm. The 0-1 in
# heightmap bitmap is multiplied by `heightmult`, and that's how many
# metres 1 is.
[Map]
heightmult=16
heightmap=res/map/heightmap.png
texturemap=res/map/texturemap.png
entitymap=res/map/entitymap.png
# The scripts are loaded and executed after everything above has been
# loaded, so that Guile has some stuff to work with.
[Scripts]
global=res/scripts/ui_styles.scm;res/scripts/ui_composites.scm
+15 -13
View File
@@ -1,18 +1,20 @@
(register-entity-template
"tree"
#:mesh-type 'quad-x
#:cull-distance 70 ;in %
#:wavy #t
#:scale '(3.0 8.0 3.0)
#:texture (get-texture "tree0")
#:program (get-program "default"))
(entity-new
#:mesh-type 'quad-x
#:cull-distance 70 ;in %
#:wavy #t
#:scale '(3.0 8.0 3.0)
#:texture (pak-texture "base" "tree0")
#:program (pak-program "base" "default")))
(register-entity-template
"grass"
#:mesh-type 'quad-1
#:render-type 'billboard-y
#:cull-distance 20 ;in %
#:wavy #t
#:scale '(1.0 0.5 1.0)
#:texture (get-texture "grass0")
#:program (get-program "default"))
(entity-new
#:mesh-type 'quad-1
#:render-type 'billboard-y
#:cull-distance 20 ;in %
#:wavy #t
#:scale '(1.0 0.5 1.0)
#:texture (pak-texture "base" "grass0")
#:program (pak-program "base" "default")))
-19
View File
@@ -1,19 +0,0 @@
(register-program "default" "res/shaders/default.vert" "res/shaders/default.frag")
(register-program "chunk" "res/shaders/chunk.vert" "res/shaders/chunk.frag")
(register-program "clouds" "res/shaders/clouds.vert" "res/shaders/clouds.frag")
(register-program "uiwidget" "res/shaders/uiwidget.vert" "res/shaders/uiwidget.frag")
(register-program "uitext" "res/shaders/uitext.vert" "res/shaders/uitext.frag")
(register-program "uidummy" "res/shaders/uidummy.vert" "res/shaders/uidummy.frag")
(register-texture "terrain0" "res/textures/dirt.png")
(register-texture "terrain1" "res/textures/drygrass.png")
(register-texture "terrain2" "res/textures/grass.png")
(register-texture "terrain3" "res/textures/rock_cement.png")
(register-texture "terrain4" "res/textures/asphalt_gravel.png")
(register-texture "tree0" "res/textures/tree.png")
(register-texture "grass0" "res/textures/grass0.png")
(register-texture "clouds" "res/textures/clouds.png")
(register-texture "font0" "res/textures/font_9x20.png")
(register-texture "icons" "res/textures/icons.png")
+7 -7
View File
@@ -160,13 +160,13 @@ chunkman_render (vec3 position, vec4 planes[6])
int cx = 0, cz = 0;
chunkman_world_to_chunk (position[0], position[2], &cx, &cz);
program_use (RESPRG ("chunk"));
program_use (PMPRG ("chunk"));
texture_use (RESTEX ("terrain0"), 0);
texture_use (RESTEX ("terrain1"), 1);
texture_use (RESTEX ("terrain2"), 2);
texture_use (RESTEX ("terrain3"), 3);
texture_use (RESTEX ("terrain4"), 4);
texture_use (PMTEX ("terrain0"), 0);
texture_use (PMTEX ("terrain1"), 1);
texture_use (PMTEX ("terrain2"), 2);
texture_use (PMTEX ("terrain3"), 3);
texture_use (PMTEX ("terrain4"), 4);
int render_distance = gvar_get ("render_distance");
int frame_chunks = 0;
@@ -202,7 +202,7 @@ chunkman_render (vec3 position, vec4 planes[6])
bound = true;
}
program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM);
program_set_vec3_ind (PMPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM);
ChunkMesh_render (mesh, FLAG_GET ("wireframe_enabled"));
frame_chunks++;
}
+1
View File
@@ -9,6 +9,7 @@
#include "../entity/entman.h"
#include "../graphics.h"
#include "../gvar.h"
#include "../pak/pakman.h"
#define TERRAIN_HEIGHT 8.0
+110
View File
@@ -0,0 +1,110 @@
#include "entity_guile.h"
static int
_symbol_to_mesh_type (SCM sym)
{
if (scm_is_eq (sym, scm_from_utf8_symbol ("quad-x"))) return MESH_QUAD_X;
if (scm_is_eq (sym, scm_from_utf8_symbol ("quad-2"))) return MESH_QUAD2;
return MESH_QUAD1;
}
static int
_symbol_to_origin (SCM sym)
{
if (scm_is_eq (sym, scm_from_utf8_symbol ("bottom"))) return ORIGIN_BOTTOM;
return ORIGIN_CENTER;
}
static int
_symbol_to_render_type (SCM sym)
{
if (scm_is_eq (sym, scm_from_utf8_symbol ("billboard-y"))) return RENDER_BILLBOARD_Y;
if (scm_is_eq (sym, scm_from_utf8_symbol ("billboard"))) return RENDER_BILLBOARD;
return RENDER_NORMAL;
}
static SCM
_scm_entity_new (SCM rest)
{
Entity *e = Entity_new ();
while (!scm_is_null (rest))
{
SCM keyword = scm_car (rest); rest = scm_cdr (rest);
SCM value = scm_car (rest); rest = scm_cdr (rest);
SCM sym = scm_keyword_to_symbol (keyword);
const char *kw = scm_to_utf8_string (scm_symbol_to_string (sym));
if (g_strcmp0 (kw, "mesh-type") == 0)
{
e->mesh_type = _symbol_to_mesh_type (value);
}
if (g_strcmp0 (kw, "origin") == 0)
{
e->mesh_type = _symbol_to_origin (value);
}
else if (g_strcmp0 (kw, "render-type") == 0)
{
e->render_type = _symbol_to_render_type (value);
}
else if (g_strcmp0 (kw, "visible") == 0)
{
e->visible = scm_is_true (value);
}
else if (g_strcmp0 (kw, "dont-cull") == 0)
{
e->dont_cull = scm_is_true (value);
}
else if (g_strcmp0 (kw, "cull-distance") == 0)
{
e->cull_distance = scm_to_int (value);
}
else if (g_strcmp0 (kw, "wavy") == 0)
{
e->wavy = scm_is_true (value);
}
else if (g_strcmp0 (kw, "scale") == 0)
{
for (int i = 0; i < 3; ++i)
{
e->scale[i] = scm_to_double (scm_list_ref (value, scm_from_int (i)));
}
}
else if (g_strcmp0 (kw, "texture") == 0)
{
e->texture = scm_to_int (value);
}
else if (g_strcmp0 (kw, "program") == 0)
{
e->program = scm_to_int (value);
}
}
return scm_from_pointer (e, NULL);
}
static SCM
_scm_register_entity_template (SCM name_scm, SCM ent_scm)
{
char *key = scm_to_utf8_string (name_scm);
Entity *ent = scm_to_pointer (ent_scm);
ent_templates_add (key, ent);
return SCM_UNSPECIFIED;
}
void
entity_guile_register ()
{
scm_c_define_gsubr ("entity-new", 0, 0, 1, _scm_entity_new);
scm_c_define_gsubr ("register-entity-template", 2, 0, 0, _scm_register_entity_template);
}
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <libguile.h>
#include "templates.h"
void entity_guile_register ();
+2 -2
View File
@@ -51,8 +51,8 @@ entman_init ()
glm_vec3_copy ((vec3) { 5000.0, 5000.0, 5000.0 }, sky_entity->scale);
glm_vec3_copy ((vec3) { 0.0, 200.0, 0.0 }, sky_entity->position);
glm_vec3_copy ((vec3) { 90.0, 0.0, 0.0 }, sky_entity->rotation);
sky_entity->texture = RESTEX ("clouds");
sky_entity->program = RESPRG ("clouds");
sky_entity->texture = PMTEX ("clouds");
sky_entity->program = PMPRG ("clouds");
ENTADD (sky_entity);
}
+1 -1
View File
@@ -10,11 +10,11 @@
#include "templates.h"
#include "../gl/mesh.h"
#include "../util.h"
#include "../resources.h"
#include "../state.h"
#include "../chunk/chunkman.h"
#include "../graphics.h"
#include "../gvar.h"
#include "../pak/pakman.h"
#define ENTADD(entity) (entman_add_entity (entity))
+3 -96
View File
@@ -2,24 +2,9 @@
static GHashTable *templates;
static inline void
ent_templates_add (char *key, Entity *entity)
{
g_hash_table_insert (templates, key, entity);
}
Entity *
ent_templates_get (char *key)
{
return (Entity *) g_hash_table_lookup (templates, key);
}
Entity *
ent_templates_clone (char *key)
{
return g_memdup2 (ent_templates_get (key), sizeof (Entity));
}
Entity *ent_templates_get (char *key) { return (Entity *) g_hash_table_lookup (templates, key); }
void ent_templates_add (char *key, Entity *entity) { g_hash_table_insert (templates, key, entity); }
Entity *ent_templates_clone (char *key) { return g_memdup2 (ent_templates_get (key), sizeof (Entity)); }
void
ent_templates_init ()
@@ -27,81 +12,3 @@ ent_templates_init ()
templates = g_hash_table_new (g_str_hash, g_str_equal);
scm_c_primitive_load ("res/scripts/entity_templates.scm");
}
static int
symbol_to_mesh_type (SCM sym)
{
if (scm_is_eq (sym, scm_from_utf8_symbol ("quad-x"))) return MESH_QUAD_X;
if (scm_is_eq (sym, scm_from_utf8_symbol ("quad-1"))) return MESH_QUAD1;
return 0;
}
static int
symbol_to_render_type (SCM sym)
{
if (scm_is_eq (sym, scm_from_utf8_symbol ("billboard-y"))) return RENDER_BILLBOARD_Y;
return 0;
}
static SCM
_scm_register_entity_template (SCM name_scm, SCM rest)
{
Entity *e = Entity_new ();
const char *key = scm_to_utf8_string (name_scm);
while (!scm_is_null (rest))
{
SCM keyword = scm_car (rest); rest = scm_cdr (rest);
SCM value = scm_car (rest); rest = scm_cdr (rest);
SCM sym = scm_keyword_to_symbol (keyword);
const char *kw = scm_to_utf8_string (scm_symbol_to_string (sym));
if (g_strcmp0 (kw, "mesh-type") == 0)
{
e->mesh_type = symbol_to_mesh_type (value);
}
else if (g_strcmp0 (kw, "render-type") == 0)
{
e->render_type = symbol_to_render_type (value);
}
else if (g_strcmp0 (kw, "cull-distance") == 0)
{
e->cull_distance = scm_to_int (value);
}
else if (g_strcmp0 (kw, "wavy") == 0)
{
e->wavy = scm_is_true (value);
}
else if (g_strcmp0 (kw, "scale") == 0)
{
for (int i = 0; i < 3; ++i)
{
e->scale[i] = scm_to_double (scm_list_ref (value, scm_from_int (i)));
}
}
else if (g_strcmp0 (kw, "texture") == 0)
{
e->texture = scm_to_int (value);
}
else if (g_strcmp0 (kw, "program") == 0)
{
e->program = scm_to_int (value);
}
}
ent_templates_add ((char *) key, e);
return SCM_UNSPECIFIED;
}
void
ent_templates_guile_register ()
{
scm_c_define_gsubr ("register-entity-template", 1, 0, 1, _scm_register_entity_template);
}
+4 -3
View File
@@ -4,12 +4,13 @@
#include <glib-2.0/glib.h>
#include <cglm/cglm.h>
#include <libguile.h>
#include "entity.h"
#include "../resources.h"
void ent_templates_init ();
void ent_templates_guile_register ();
Entity *ent_templates_clone (char *key);
Entity *ent_templates_get (char *key);
void ent_templates_add (char *key, Entity *entity);
Entity *ent_templates_clone (char *key);
+3 -3
View File
@@ -68,9 +68,9 @@ graphics_render ()
camera_get_projection (gvar_get ("window_width") / gvar_get ("window_height"), projection);
camera_get_view (view);
resources_programs_set_mat4 ("projection", &projection);
resources_programs_set_mat4 ("view", &view);
resources_programs_set_float ("time", gvar_get ("last_time"));
pakman_all_paks_set_mat4 ("projection", projection);
pakman_all_paks_set_mat4 ("view", view);
pakman_all_paks_set_float ("time", gvar_get ("last_time"));
vec4 planes[6];
#if FRUSTUM_CULL
+1 -1
View File
@@ -8,9 +8,9 @@
#include "chunk/chunkman.h"
#include "entity/entman.h"
#include "state.h"
#include "resources.h"
#include "util.h"
#include "gvar.h"
#include "pak/pakman.h"
#define FRUSTUM_CULL 1
+7 -4
View File
@@ -5,12 +5,14 @@
#include "event/evtman.h"
#include "chunk/chunkman.h"
#include "entity/templates.h"
#include "entity/entity_guile.h"
#include "ui/uiman.h"
#include "ui/widget_guile.h"
#include "state.h"
#include "resources.h"
#include "graphics.h"
#include "gvar.h"
#include "pak/pakman.h"
#include "pak/pak_guile.h"
extern vec3 camera_position;
@@ -22,13 +24,14 @@ SDL_AppInit (void **appstate, int argc, char **argv)
scm_init_guile ();
gvar_guile_register ();
resources_guile_register ();
widget_guile_register ();
ent_templates_guile_register ();
entity_guile_register ();
pak_guile_register ();
gvar_init ();
graphics_init ();
resources_init ();
pakman_init ();
pakman_load_pak ("res/");
evtman_init ();
uiman_init ();
+24
View File
@@ -0,0 +1,24 @@
#include "pak_guile.h"
static SCM
_scm_get_program (SCM pak_scm, SCM key_scm)
{
const char *pak = scm_to_utf8_string (pak_scm);
const char *key = scm_to_utf8_string (key_scm);
return scm_from_int (pakman_pak_program (pak, key));
}
static SCM
_scm_get_texture (SCM pak_scm, SCM key_scm)
{
const char *pak = scm_to_utf8_string (pak_scm);
const char *key = scm_to_utf8_string (key_scm);
return scm_from_int (pakman_pak_texture (pak, key));
}
void
pak_guile_register ()
{
scm_c_define_gsubr ("pak-program", 2, 0, 0, _scm_get_program);
scm_c_define_gsubr ("pak-texture", 2, 0, 0, _scm_get_texture);
}
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <libguile.h>
#include "pakman.h"
void pak_guile_register ();
+193
View File
@@ -0,0 +1,193 @@
#include "pakman.h"
static GHashTable *paks;
void
pakman_init ()
{
paks = g_hash_table_new (g_str_hash, g_str_equal);
}
unsigned int
_pm_load_program (const char *v_path, const char *f_path)
{
char *v_src;
if (!g_file_get_contents (v_path, &v_src, NULL, NULL))
{
g_warning ("File `%s' does not exist.", v_path);
}
char *f_src;
if (!g_file_get_contents (f_path, &f_src, NULL, NULL))
{
g_warning ("File `%s' does not exist.", f_path);
}
unsigned int program = program_create (v_src, f_src);
g_free (v_src);
g_free (f_src);
return program;
}
unsigned int
_pm_load_texture (const char *path)
{
SDL_Surface *surface = IMG_Load (path);
if (surface == NULL)
{
g_warning ("Failed to load texture from path %s: %s", path, SDL_GetError ());
return 0;
}
unsigned int texture = texture_create (surface->w, surface->h, surface->pixels);
return texture;
}
void
pakman_load_pak (const char *path)
{
GError *err = NULL;
GKeyFile *key_file = g_key_file_new ();
char *manifest_path = g_build_filename (path, "manifest.cfg", NULL);
g_debug ("Loading .pak mainfest from %s...", manifest_path);
if (!g_key_file_load_from_file (key_file, manifest_path, G_KEY_FILE_NONE, &err))
{
g_error ("Error loading .pak manifest.cfg: %s", err->message);
return;
}
PakFile *pak = g_new0 (PakFile, 1);
pak->programs = g_hash_table_new (g_str_hash, g_str_equal);
pak->textures = g_hash_table_new (g_str_hash, g_str_equal);
char **programs = g_key_file_get_keys (key_file, "Programs", NULL, &err);
for (char **p = programs; *p != NULL; p++)
{
size_t n_shaders;
char **shaders = g_key_file_get_string_list (key_file, "Programs", *p, &n_shaders, &err);
if (n_shaders == 2)
{
g_hash_table_insert (pak->programs, g_strdup (*p), GUINT_TO_POINTER (_pm_load_program (shaders[0], shaders[1])));
}
else
{
g_warning ("Program %s does not have 2 shaders.", *p);
}
}
char **textures = g_key_file_get_keys (key_file, "Textures", NULL, &err);
for (char **t = textures; *t != NULL; t++)
{
char *texture = g_key_file_get_string (key_file, "Textures", *t, &err);
g_hash_table_insert (pak->textures, g_strdup (*t), GUINT_TO_POINTER (_pm_load_texture (texture)));
}
char *id = g_key_file_get_string (key_file, "Metadata", "id", &err);
g_hash_table_insert (paks, g_strdup (id), pak);
/* Some hacks. */
program_use (pakman_pak_program (id, "chunk"));
program_set_int_array (pakman_pak_program (id, "chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });
program_use (pakman_pak_program (id, "uiwidget"));
program_set_int (pakman_pak_program (id, "uiwidget"), "background_image", 0);
program_set_int (pakman_pak_program (id, "uiwidget"), "icons", 1);
g_key_file_free (key_file);
}
unsigned int
pakman_pak_program (const char *pak, const char *program)
{
PakFile *p = g_hash_table_lookup (paks, pak);
if (!p)
{
g_warning ("Pak `%s' not found.", pak);
return 0;
}
gpointer value = g_hash_table_lookup (p->programs, program);
if (!value)
{
g_warning ("Program `%s' not found in pak `%s'.", program, pak);
return 0;
}
return GPOINTER_TO_UINT (value);
}
unsigned int
pakman_pak_texture (const char *pak, const char *texture)
{
PakFile *p = g_hash_table_lookup (paks, pak);
if (!p)
{
g_warning ("Pak `%s' not found.", pak);
return 0;
}
gpointer value = g_hash_table_lookup (p->textures, texture);
if (!value)
{
g_warning ("Texture `%s' not found in pak `%s'.", texture, pak);
return 0;
}
return GPOINTER_TO_UINT (value);
}
void
pakman_all_paks_set_mat4 (const char *uniform, mat4 value)
{
GHashTableIter pack_iter;
PakFile *pak;
g_hash_table_iter_init (&pack_iter, paks);
while (g_hash_table_iter_next (&pack_iter, NULL, (void **) &pak))
{
GHashTableIter program_iter;
void *program_value;
g_hash_table_iter_init (&program_iter, pak->programs);
while (g_hash_table_iter_next (&program_iter, NULL, (void **) &program_value))
{
unsigned int program = GPOINTER_TO_UINT (program_value);
program_use (program);
program_set_mat4 (program, uniform, value);
}
}
}
void
pakman_all_paks_set_float (const char *uniform, float value)
{
GHashTableIter pack_iter;
PakFile *pak;
g_hash_table_iter_init (&pack_iter, paks);
while (g_hash_table_iter_next (&pack_iter, NULL, (void **) &pak))
{
GHashTableIter program_iter;
void *program_value;
g_hash_table_iter_init (&program_iter, pak->programs);
while (g_hash_table_iter_next (&program_iter, NULL, (void **) &program_value))
{
unsigned int program = GPOINTER_TO_UINT (program_value);
program_use (program);
program_set_float (program, uniform, value);
}
}
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <SDL3_image/SDL_image.h>
#include <glib-2.0/glib.h>
#include <cglm/cglm.h>
#include "../gl/program.h"
#include "../gl/texture.h"
#include "../util.h"
typedef struct PakFile
{
GHashTable *programs;
GHashTable *textures;
} PakFile;
void pakman_init ();
void pakman_load_pak (const char *path);
unsigned int pakman_pak_program (const char *pak, const char *program);
unsigned int pakman_pak_texture (const char *pak, const char *texture);
void pakman_all_paks_set_mat4 (const char *uniform, mat4 value);
void pakman_all_paks_set_float (const char *uniform, float value);
#define PMPRG(program) pakman_pak_program ("base", program)
#define PMTEX(texture) pakman_pak_texture ("base", texture)
-196
View File
@@ -1,196 +0,0 @@
#include "resources.h"
SDL_Surface *resources_cursor;
static GHashTable *programs;
static GHashTable *textures;
unsigned int
resources_load_program (const char *v_path, const char *f_path)
{
char *v_src;
if (!g_file_get_contents (v_path, &v_src, NULL, NULL))
{
g_warning ("File `%s' does not exist.", v_path);
}
char *f_src;
if (!g_file_get_contents (f_path, &f_src, NULL, NULL))
{
g_warning ("File `%s' does not exist.", f_path);
}
unsigned int program = program_create (v_src, f_src);
g_free (v_src);
g_free (f_src);
return program;
}
unsigned int
resources_load_texture (const char *path)
{
SDL_Surface *surface = IMG_Load (path);
if (surface == NULL)
{
g_warning ("Failed to load texture from path %s: %s", path, SDL_GetError ());
return 0;
}
unsigned int texture = texture_create (surface->w, surface->h, surface->pixels);
return texture;
}
static inline void
resources_add_program (char *key, unsigned int program)
{
if (program)
{
g_hash_table_insert (programs, key, GINT_TO_POINTER (program));
}
}
static inline void
resources_add_texture (char *key, unsigned int texture)
{
if (texture)
{
g_hash_table_insert (textures, key, GINT_TO_POINTER (texture));
}
}
unsigned int
resources_get_program (char *key)
{
if (!g_hash_table_contains (programs, key))
{
g_warning ("Program `%s' does not exist. Careful!", key);
}
return GPOINTER_TO_INT (g_hash_table_lookup (programs, key));
}
unsigned int
resources_get_texture (char *key)
{
if (!g_hash_table_contains (textures, key))
{
g_warning ("Texture `%s' does not exist. Careful!", key);
}
return GPOINTER_TO_INT (g_hash_table_lookup (textures, key));
}
void
res_mat4_internal (gpointer key, gpointer value, gpointer userdata)
{
UNUSED (key);
unsigned int program = GPOINTER_TO_INT (value);
struct {
const char *name;
mat4 *mat;
} *data = userdata;
program_use (program);
program_set_mat4 (program, data->name, *data->mat);
}
void
res_float_internal (gpointer key, gpointer value, gpointer userdata)
{
UNUSED (key);
unsigned int program = GPOINTER_TO_INT (value);
struct {
const char *name;
float val;
} *data = userdata;
program_use (program);
program_set_float (program, data->name, data->val);
}
void
resources_programs_set_float (const char *name, float value)
{
struct {
const char *name;
float val;
} data = { name, value };
g_hash_table_foreach (programs, res_float_internal, &data);
}
void
resources_programs_set_mat4 (const char *name, mat4 *value)
{
struct {
const char *name;
mat4 *mat;
} data = { name, value };
g_hash_table_foreach (programs, res_mat4_internal, &data);
}
void
resources_init ()
{
programs = g_hash_table_new (g_str_hash, g_str_equal);
textures = g_hash_table_new (g_str_hash, g_str_equal);
scm_c_primitive_load ("res/scripts/resources.scm");
program_use (RESPRG ("chunk"));
program_set_int_array (RESPRG ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });
program_use (RESPRG ("uiwidget"));
program_set_int (RESPRG ("uiwidget"), "background_image", 0);
program_set_int (RESPRG ("uiwidget"), "icons", 1);
}
static SCM
_scm_register_program (SCM key_scm, SCM vpath_scm, SCM fpath_scm)
{
const char *key = scm_to_utf8_string (key_scm);
const char *vpath = scm_to_utf8_string (vpath_scm);
const char *fpath = scm_to_utf8_string (fpath_scm);
unsigned int prog = resources_load_program (vpath, fpath);
resources_add_program ((char *) key, prog);
return SCM_UNSPECIFIED;
}
static SCM
_scm_register_texture (SCM key_scm, SCM path_scm)
{
const char *key = scm_to_utf8_string (key_scm);
const char *path = scm_to_utf8_string (path_scm);
unsigned int tex = resources_load_texture (path);
resources_add_texture ((char *) key, tex);
return SCM_UNSPECIFIED;
}
static SCM
_scm_get_program (SCM key_scm)
{
const char *key = scm_to_utf8_string (key_scm);
return scm_from_int (resources_get_program ((char *) key));
}
static SCM
_scm_get_texture (SCM key_scm)
{
const char *key = scm_to_utf8_string (key_scm);
return scm_from_int (resources_get_texture ((char *) key));
}
void
resources_guile_register ()
{
scm_c_define_gsubr ("register-program", 3, 0, 0, _scm_register_program);
scm_c_define_gsubr ("register-texture", 2, 0, 0, _scm_register_texture);
scm_c_define_gsubr ("get-program", 1, 0, 0, _scm_get_program);
scm_c_define_gsubr ("get-texture", 1, 0, 0, _scm_get_texture);
}
-20
View File
@@ -1,20 +0,0 @@
#pragma once
#include <SDL3_image/SDL_image.h>
#include <glib-2.0/glib.h>
#include <cglm/cglm.h>
#include <libguile.h>
#include "gl/program.h"
#include "gl/texture.h"
#include "util.h"
#define RESPRG(key) (resources_get_program (key))
#define RESTEX(key) (resources_get_texture (key))
void resources_programs_set_float (const char *name, float value);
void resources_programs_set_mat4 (const char *name, mat4 *mat);
unsigned int resources_get_program (char *key);
unsigned int resources_get_texture (char *key);
void resources_init ();
void resources_guile_register ();
+1 -1
View File
@@ -10,7 +10,7 @@
#include "widget_boilerplate.h"
#include "../util.h"
#include "../resources.h"
#include "../pak/pakman.h"
#include "../gl/mesh.h"
#include "../gl/program.h"
+44 -45
View File
@@ -19,9 +19,9 @@ static inline void
_Widget_render_text_line(const char *text, TextAlignment alignment, ivec2 position,
ivec2 size, int max_width, const vec4 color, mat4 projection)
{
program_use (RESPRG ("uitext"));
program_set_mat4 (RESPRG ("uitext"), "projection", projection);
program_set_vec4 (RESPRG ("uitext"), "color", color);
program_use (PMPRG ("uitext"));
program_set_mat4 (PMPRG ("uitext"), "projection", projection);
program_set_vec4 (PMPRG ("uitext"), "color", color);
int nchars = g_utf8_strlen (text, -1);
int total_w = nchars * size[0];
@@ -45,12 +45,12 @@ _Widget_render_text_line(const char *text, TextAlignment alignment, ivec2 positi
while (*p)
{
gunichar ch = g_utf8_get_char (p);
program_set_float (RESPRG ("uitext"), "character", ch);
program_set_float (PMPRG ("uitext"), "character", ch);
mat3 model;
glm_translate2d_make (model, (vec2) { position[0] + xoff, position[1] });
glm_scale2d (model, (vec2) { size[0], size[1] });
program_set_mat3 (RESPRG ("uitext"), "model", model);
program_set_mat3 (PMPRG ("uitext"), "model", model);
SimpleMesh_render (&quad, FALSE);
@@ -74,42 +74,41 @@ Widget_render_base (Widget *self, mat4 projection, int window_height)
const WidgetStyle *style = self->style;
program_use (RESPRG ("uiwidget"));
program_use (PMPRG ("uiwidget"));
texture_use (style->background_image, 0); /* If it doesn't have a texture, it'll be 0 anyway. */
texture_use (RESTEX ("icons"), 1);
texture_use (PMTEX ("icons"), 1);
program_set_int (RESPRG ("uiwidget"), "has_background_image", style->background_image != 0);
program_set_int (RESPRG ("uiwidget"), "has_icon", self->icon != ICON_NONE);
program_set_int (RESPRG ("uiwidget"), "has_resize_handle", self->kind == WIDGET_WINDOW);
program_set_int (PMPRG ("uiwidget"), "has_background_image", style->background_image != 0);
program_set_int (PMPRG ("uiwidget"), "has_icon", self->icon != ICON_NONE);
program_set_int (PMPRG ("uiwidget"), "has_resize_handle", self->kind == WIDGET_WINDOW);
program_set_vec2 (RESPRG ("uiwidget"), "widget_size", (vec2) { self->size[0], self->size[1] });
program_set_float (RESPRG ("uiwidget"), "border_width", style->border_width);
program_set_float (RESPRG ("uiwidget"), "icon_index", self->icon - 1);
program_set_vec2 (PMPRG ("uiwidget"), "widget_size", (vec2) { self->size[0], self->size[1] });
program_set_float (PMPRG ("uiwidget"), "border_width", style->border_width);
program_set_float (PMPRG ("uiwidget"), "icon_index", self->icon - 1);
program_set_vec4 (RESPRG ("uiwidget"), "background_color", style->background_color);
program_set_vec4 (RESPRG ("uiwidget"), "icon_color", style->icon_color);
program_set_vec4 (RESPRG ("uiwidget"), "border_color", style->border_color);
program_set_vec4 (RESPRG ("uiwidget"), "resize_handle_color", style->resize_handle_color);
program_set_vec4 (PMPRG ("uiwidget"), "background_color", style->background_color);
program_set_vec4 (PMPRG ("uiwidget"), "icon_color", style->icon_color);
program_set_vec4 (PMPRG ("uiwidget"), "border_color", style->border_color);
program_set_vec4 (PMPRG ("uiwidget"), "resize_handle_color", style->resize_handle_color);
if (self->clicked)
{
program_set_vec4 (RESPRG ("uiwidget"), "background_color", style->background_color_clicked);
program_set_vec4 (RESPRG ("uiwidget"), "icon_color", style->icon_color_clicked);
program_set_vec4 (PMPRG ("uiwidget"), "background_color", style->background_color_clicked);
program_set_vec4 (PMPRG ("uiwidget"), "icon_color", style->icon_color_clicked);
}
else if (self->hovered)
{
program_set_vec4 (RESPRG ("uiwidget"), "background_color", style->background_color_hovered);
program_set_vec4 (RESPRG ("uiwidget"), "icon_color", style->icon_color_hovered);
program_set_vec4 (PMPRG ("uiwidget"), "background_color", style->background_color_hovered);
program_set_vec4 (PMPRG ("uiwidget"), "icon_color", style->icon_color_hovered);
}
mat3 model;
glm_translate2d_make (model, (vec2) { self->position[0], self->position[1] });
glm_scale2d (model, (vec2) { self->size[0], self->size[1] });
program_set_mat3 (RESPRG ("uiwidget"), "model", model);
program_set_mat4 (RESPRG ("uiwidget"), "projection", projection);
program_set_mat3 (PMPRG ("uiwidget"), "model", model);
program_set_mat4 (PMPRG ("uiwidget"), "projection", projection);
/* Before we render, we calculate the scissor box based on the
parents. */
@@ -145,7 +144,7 @@ Widget_render_label (Widget *self, mat4 projection, int window_height)
ivec2 pos = { self->position[0], self->position[1] };
const WidgetStyle *style = self->style;
texture_use (RESTEX ("font0"), 0);
texture_use (PMTEX ("font0"), 0);
_Widget_render_text_line (self->label.text->str, self->label.text_alignment,
pos, (ivec2) { char_w, self->size[1] }, self->size[0],
self->clicked ? style->text_color_clicked : self->hovered
@@ -155,20 +154,20 @@ Widget_render_label (Widget *self, mat4 projection, int window_height)
void
Widget_render_scrollbar (Widget *self, mat4 projection, int window_height)
{
program_use (RESPRG ("uiwidget"));
program_set_int (RESPRG ("uiwidget"), "has_scrollbar", TRUE);
program_use (PMPRG ("uiwidget"));
program_set_int (PMPRG ("uiwidget"), "has_scrollbar", TRUE);
const WidgetStyle *style = self->style;
program_set_vec4 (RESPRG ("uiwidget"), "scrollbar_color", style->scrollbar_color);
program_set_vec4 (PMPRG ("uiwidget"), "scrollbar_color", style->scrollbar_color);
if (self->clicked)
{
program_set_vec4 (RESPRG ("uiwidget"), "scrollbar_color", style->scrollbar_color_clicked);
program_set_vec4 (PMPRG ("uiwidget"), "scrollbar_color", style->scrollbar_color_clicked);
}
else if (self->hovered)
{
program_set_vec4 (RESPRG ("uiwidget"), "scrollbar_color", style->scrollbar_color_hovered);
program_set_vec4 (PMPRG ("uiwidget"), "scrollbar_color", style->scrollbar_color_hovered);
}
/* Calculate the scrollbar size. */
@@ -182,35 +181,35 @@ Widget_render_scrollbar (Widget *self, mat4 projection, int window_height)
int thumb_size_norm = view_size / content_size;
int thumb_pos_norm = scroll_pos / content_size;
program_set_vec2 (RESPRG ("uiwidget"), "scrollbar_position", self->scrollbar.horizontal
program_set_vec2 (PMPRG ("uiwidget"), "scrollbar_position", self->scrollbar.horizontal
? (vec2) { thumb_pos_norm, 0.0f }
: (vec2) { 0.0f, thumb_pos_norm });
program_set_vec2 (RESPRG ("uiwidget"), "scrollbar_size", self->scrollbar.horizontal
program_set_vec2 (PMPRG ("uiwidget"), "scrollbar_size", self->scrollbar.horizontal
? (vec2) { thumb_size_norm, 1.0f }
: (vec2) { 1.0f, thumb_size_norm });
Widget_render_base (self, projection, window_height);
program_set_int (RESPRG ("uiwidget"), "has_scrollbar", FALSE);
program_set_int (PMPRG ("uiwidget"), "has_scrollbar", FALSE);
}
void
Widget_render_progress (Widget *self, mat4 projection, int window_height)
{
program_use (RESPRG ("uiwidget"));
program_set_int (RESPRG ("uiwidget"), "has_progress", TRUE);
program_use (PMPRG ("uiwidget"));
program_set_int (PMPRG ("uiwidget"), "has_progress", TRUE);
float bar_size = (*self->progress.ptr - self->progress.min) / (self->progress.max - self->progress.min);
bar_size = glm_clamp (bar_size, 0.0, 1.0);
program_set_vec4 (RESPRG ("uiwidget"), "progress_color", self->style->progress_color);
program_set_vec4 (PMPRG ("uiwidget"), "progress_color", self->style->progress_color);
program_set_vec2 (RESPRG ("uiwidget"), "progress_size", self->progress.horizontal
program_set_vec2 (PMPRG ("uiwidget"), "progress_size", self->progress.horizontal
? (vec2) { bar_size, 1.0f }
: (vec2) { 1.0f, bar_size });
Widget_render_base (self, projection, window_height);
program_set_int (RESPRG ("uiwidget"), "has_progress", FALSE);
program_set_int (PMPRG ("uiwidget"), "has_progress", FALSE);
}
void
@@ -218,7 +217,7 @@ Widget_render_multiline_text (Widget *self, mat4 projection, int window_height)
{
Widget_render_base (self, projection, window_height);
texture_use (RESTEX ("font0"), 0);
texture_use (PMTEX ("font0"), 0);
int pad = self->layout_padding;
int row_h = self->multiline_text.line_height;
@@ -240,7 +239,7 @@ Widget_render_entry (Widget *self, mat4 projection, int window_height)
{
Widget_render_base (self, projection, window_height);
texture_use (RESTEX ("font0"), 0);
texture_use (PMTEX ("font0"), 0);
int char_w = self->size[1] * (9.0f / 20.0f);
int cursor_in_px = self->entry.cursor_position * char_w;
@@ -273,10 +272,10 @@ Widget_render_entry (Widget *self, mat4 projection, int window_height)
glm_translate2d_make (model, (vec2) { x, y });
glm_scale2d (model, (vec2) { w, h });
program_use (RESPRG ("uidummy"));
program_set_mat3 (RESPRG ("uidummy"), "model", model);
program_set_mat4 (RESPRG ("uidummy"), "projection", projection);
program_set_vec4 (RESPRG ("uidummy"), "background_color", self->style->text_color);
program_use (PMPRG ("uidummy"));
program_set_mat3 (PMPRG ("uidummy"), "model", model);
program_set_mat4 (PMPRG ("uidummy"), "projection", projection);
program_set_vec4 (PMPRG ("uidummy"), "background_color", self->style->text_color);
SimpleMesh_render (&quad, FALSE);
}
@@ -288,7 +287,7 @@ Widget_render_window (Widget *self, mat4 projection, int window_height)
UNUSED (self, projection, window_height);
Widget_render_base (self, projection, window_height);
texture_use (RESTEX ("font0"), 0);
texture_use (PMTEX ("font0"), 0);
ivec2 pos = {
self->position[0] + self->layout_padding,