Files
wschod/game/src/pakman.c
T
2025-07-21 21:00:00 +02:00

259 lines
6.5 KiB
C

#include "pakman.h"
static GHashTable *paks;
void
pakman_init ()
{
paks = g_hash_table_new (g_str_hash, g_str_equal);
}
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));
}
static SCM
_scm_get_uidef (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_pointer (pakman_pak_uidef (pak, key), NULL);
}
void
pakman_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);
scm_c_define_gsubr ("pak-uidef", 2, 0, 0, _scm_get_uidef);
}
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);
pak->uidefs = 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 **uidefs = g_key_file_get_keys (key_file, "UIDefs", NULL, &err);
for (char **u = uidefs; *u != NULL; u++)
{
char *uidef_path = g_key_file_get_string (key_file, "UIDefs", *u, &err);
SCM uidef_scm = scm_c_primitive_load (uidef_path);
Widget *uidef = (Widget *) scm_to_pointer (uidef_scm);
g_hash_table_insert (pak->uidefs, g_strdup (*u), uidef);
}
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);
}
Widget *
pakman_pak_uidef (const char *pak, const char *uidef)
{
PakFile *p = g_hash_table_lookup (paks, pak);
if (!p)
{
g_warning ("Pak `%s' not found.", pak);
return NULL;
}
Widget *value = g_hash_table_lookup (p->uidefs, uidef);
if (!value)
{
g_warning ("Uidef `%s' not found in pak `%s'.", uidef, pak);
return NULL;
}
return 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);
}
}
}