more guile features

This commit is contained in:
2025-07-20 20:23:51 +02:00
parent cc075e2cc1
commit c86b8ef7bb
10 changed files with 125 additions and 74 deletions
+28 -4
View File
@@ -1,3 +1,5 @@
(use-modules (ice-9 format))
(define (widget-checkbox-icon-switch widget event)
(if (= (widget-get-icon widget) 1)
(widget-set-icon! widget 2)
@@ -14,13 +16,35 @@
#:on-click (lambda (w e) (widget-checkbox-icon-switch w e) (flag-switch flag)))
(widget-new 'label #:style style-default #:text text #:layout-weight 1)))))
(define (widget-spinner . args)
(define (coerce type val)
(cond
((eq? type 'int) (inexact->exact (round val)))
((eq? type 'bool) (if (> val 0.5) #t #f))
(else val)))
(define (widget-spinner type fmt gvar . args)
(apply
widget-new
(append
(list 'container #:horizontal #t #:layout-spacing 8)
args
(list
(widget-new 'plain #:style style-icon-button #:icon 3 #:aspect-ratio 1)
(widget-new 'label #:style style-default #:layout-weight 1)
(widget-new 'plain #:style style-icon-button #:icon 4 #:aspect-ratio 1)))))
(widget-new 'plain #:style style-icon-button #:icon 3 #:aspect-ratio 1
#:on-click (lambda (w e)
(gvar-set gvar (- (gvar-get gvar) 1))))
(widget-new 'label #:style style-default #:layout-weight 1 #:text-alignment 'center
#:on-tick (lambda (w e)
(widget-set-text! w (apply format #f fmt (list (coerce type (gvar-get gvar)))))))
(widget-new 'plain #:style style-icon-button #:icon 4 #:aspect-ratio 1
#:on-click (lambda (w e)
(gvar-set gvar (+ (gvar-get gvar) 1))))))))
(define (widget-label-gvar type fmt gvar . args)
(apply
widget-new
(append
(list 'label
#:on-tick
(lambda (w e)
(widget-set-text! w (apply format #f fmt (list (coerce type (gvar-get gvar)))))))
args)))
+5 -6
View File
@@ -1,7 +1,6 @@
(use-modules (ice-9 format))
;; The function is evaulated and returns a pointer, the game eats it
;; and adds it to the UI root. Boom.
(gvar-set "Some crap" 100.0)
(widget-new
'window
#:style style-window
@@ -17,9 +16,9 @@
#:layout-padding 8
#:layout-spacing 8
#:horizontal #t
(widget-label-gvar 'float "Delta time: ~,2f" "delta_time" #:style style-default #:layout-weight 1 #:h 20 #:text-alignment 'center)
(widget-label-gvar 'int "Chunks: ~d" "frame_chunks" #:style style-default #:layout-weight 0.5 #:h 20)
(widget-label-gvar 'int "Entities: ~d" "frame_entities" #:style style-default #:layout-weight 0.5 #:h 20)
(widget-checkbox "Flight" "flight_enabled" #:layout-weight 0.5 #:h 20)
(widget-checkbox "Wireframe" "wireframe_enabled" #:layout-weight 0.5 #:h 20)
(widget-new 'label #:style style-default #:layout-weight 1 #:h 20
#:on-tick (lambda (w e) (widget-set-text! w (number->string (gvar-get "Some crap")))))
(widget-spinner #:layout-weight 1 #:h 20)
(widget-new 'entry #:style style-default #:layout-weight 1 #:h 20 #:text "Enter text...")))
(widget-spinner 'int "Render distance: ~d" "render_distance" #:layout-weight 1 #:h 20)))
+12 -12
View File
@@ -1,9 +1,5 @@
#include "chunkman.h"
extern int render_distance;
int n_frame_chunks;
static GHashTable *chunks;
static GHashTable *chunk_meshes;
@@ -112,6 +108,8 @@ chunkman_tick (vec3 position)
uint64_t start = SDL_GetPerformanceCounter ();
uint64_t freq = SDL_GetPerformanceFrequency ();
double elapsed_us = 0;
int render_distance = gvar_get ("render_distance");
for (int z = cz - render_distance - 1; z <= cz + render_distance + 1; ++z)
{
@@ -148,9 +146,9 @@ chunkman_tick (vec3 position)
{
chunkman_generate_ChunkMesh_at (x, z);
}
}
}
}
}
void
chunkman_render (vec3 position, vec4 planes[6])
@@ -170,7 +168,8 @@ chunkman_render (vec3 position, vec4 planes[6])
texture_use (RESTEX ("terrain3"), 3);
texture_use (RESTEX ("terrain4"), 4);
n_frame_chunks = 0;
int render_distance = gvar_get ("render_distance");
int frame_chunks = 0;
for (int z = cz - render_distance; z <= cz + render_distance; ++z)
{
@@ -178,9 +177,9 @@ chunkman_render (vec3 position, vec4 planes[6])
{
/* Render in a circle instead of a square. */
if ((x - cx) * (x - cx) + (z - cz) * (z - cz) > render_distance*render_distance)
{
continue;
}
{
continue;
}
ChunkMesh *mesh = chunkman_get_ChunkMesh_at (x, z);
if (mesh != NULL)
@@ -205,12 +204,13 @@ chunkman_render (vec3 position, vec4 planes[6])
program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM);
ChunkMesh_render (mesh, FLAG_GET ("wireframe_enabled"));
n_frame_chunks++;
frame_chunks++;
}
}
}
}
bound = false;
bound = false;
gvar_set ("frame_chunks", frame_chunks);
}
Chunk *
+11 -9
View File
@@ -7,10 +7,8 @@
seperately somehow. */
extern vec3 camera_position;
extern int render_distance;
Entity *player_entity, *sky_entity;
int n_frame_ents;
/* The GArray is the fastest of all sequence types. Should work fine
for a billion entities. */
@@ -108,7 +106,7 @@ entman_tick ()
}
}
void
gboolean
entman_render_entity (Entity *entity, void *userdata)
{
struct {
@@ -120,9 +118,10 @@ entman_render_entity (Entity *entity, void *userdata)
if (!entity->visible)
{
return;
return FALSE;
}
int render_distance = gvar_get ("render_distance");
/* Why an int, why int division? It's simply much faster than
floating point operations. No need to have super accurate cull
distance anyway, and might as well save a lot when rendering entities. */
@@ -136,7 +135,7 @@ entman_render_entity (Entity *entity, void *userdata)
if (glm_vec2_distance2 (c_xz, e_xz) > cull_dist*cull_dist && !entity->dont_cull)
{
return;
return FALSE;
}
#if FRUSTUM_CULL
@@ -145,7 +144,7 @@ entman_render_entity (Entity *entity, void *userdata)
if (!glm_aabb_frustum (aabb, *vp->frustum_planes))
{
return;
return FALSE;
}
#endif
@@ -234,7 +233,7 @@ entman_render_entity (Entity *entity, void *userdata)
}
SimpleMesh_render (&to_render, FLAG_GET ("wireframe_enabled"));
n_frame_ents++;
return TRUE;
}
void
@@ -247,7 +246,6 @@ entman_render (mat4 *view, vec4 planes[6])
last_program = -1;
last_texture = -1;
last_type = -1;
n_frame_ents = 0;
struct {
mat4 *view;
@@ -261,11 +259,15 @@ entman_render (mat4 *view, vec4 planes[6])
#endif
};
int frame_entities = 0;
for (guint i = 0; i < entities->len; ++i)
{
Entity *e = g_array_index (entities, Entity*, i);
entman_render_entity (e, &data);
frame_entities += entman_render_entity (e, &data) ? 1 : 0;
}
gvar_set ("frame_entities", frame_entities);
}
void
+15 -9
View File
@@ -1,11 +1,8 @@
#include "graphics.h"
extern vec3 camera_position;
extern int last_time;
SDL_Window *sdl_window;
int sdl_window_w = 800, sdl_window_h = 600;
int render_distance = 2;
static SDL_GLContext gl_context;
static uint64_t last_check_perf = 0;
@@ -15,12 +12,16 @@ static double avg_elapsed = 0;
void
graphics_init ()
{
gvar_set ("render_distance", 2);
gvar_set ("window_width", 800);
gvar_set ("window_height", 600);
if (!SDL_Init (SDL_INIT_VIDEO))
{
g_error ("Couldn't initialize SDL: %s", SDL_GetError ());
}
sdl_window = SDL_CreateWindow (GAME_NAME, sdl_window_w, sdl_window_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
sdl_window = SDL_CreateWindow (GAME_NAME, gvar_get ("window_width"), gvar_get ("window_height"), SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!sdl_window)
{
@@ -50,7 +51,7 @@ graphics_init ()
g_info ("GLSL version: %s", glGetString (GL_SHADING_LANGUAGE_VERSION));
g_info ("Max vertex attributes: %d", GL_MAX_VERTEX_ATTRIBS);
glViewport (0, 0, sdl_window_w, sdl_window_h);
glViewport (0, 0, gvar_get ("window_width"), gvar_get ("window_height"));
glClearColor (0, 0.3, 0.8, 1);
glEnable (GL_CULL_FACE);
@@ -68,12 +69,12 @@ graphics_render ()
uint64_t freq = SDL_GetPerformanceFrequency ();
mat4 projection, view;
camera_get_projection ((float) sdl_window_w / (float) sdl_window_h, projection);
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", last_time);
resources_programs_set_float ("time", gvar_get ("last_time"));
vec4 planes[6];
#if FRUSTUM_CULL
@@ -102,17 +103,19 @@ graphics_render ()
avg_elapsed += elapsed_us;
avg_counter++;
int render_distance = gvar_get ("render_distance");
if ((now - last_check_perf) >= freq * RENDER_AVG_FREQ_S)
{
double avg = avg_elapsed / avg_counter;
if (avg < RENDER_FRAME_BUDGET_US && render_distance < RENDER_DISTANCE_MAX)
{
render_distance++;
gvar_set ("render_distance", ++render_distance);
}
else if (avg > RENDER_FRAME_BUDGET_US && render_distance > RENDER_DISTANCE_MIN)
{
render_distance--;
gvar_set ("render_distance", --render_distance);
}
avg_elapsed = 0;
@@ -133,8 +136,11 @@ gboolean
graphics_cb_window_resize (SDL_Event *event, void *data)
{
UNUSED (event, data);
int sdl_window_w, sdl_window_h;
SDL_GetWindowSizeInPixels (sdl_window, &sdl_window_w, &sdl_window_h);
glViewport (0, 0, sdl_window_w, sdl_window_h);
gvar_set ("window_width", sdl_window_w);
gvar_set ("window_height", sdl_window_h);
/* Since other subsystems might want to use the event. */
return FALSE;
}
+1
View File
@@ -10,6 +10,7 @@
#include "state.h"
#include "resources.h"
#include "util.h"
#include "gvar.h"
#define FRUSTUM_CULL 1
+2 -2
View File
@@ -23,10 +23,10 @@ SDL_AppInit (void **appstate, int argc, char **argv)
scm_init_guile ();
gvar_guile_register ();
widget_guile_register ();
gvar_init ();
graphics_init ();
resources_init ();
gvar_init ();
evtman_init ();
uiman_init ();
chunkman_init ();
+5 -6
View File
@@ -4,22 +4,21 @@ extern vec3 camera_position;
extern vec3 camera_rotation;
extern Entity *player_entity, *sky_entity;
float delta_time;
int last_time;
void
game_state_init (int ticks)
{
last_time = ticks;
gvar_set ("last_time", ticks);
}
void
game_state_tick (int ticks)
{
/* Caluclate stuff per frame. */
delta_time = (ticks - last_time) / 1000.0;
last_time = ticks;
gvar_set ("delta_time", (ticks - gvar_get ("last_time")) / 1000.0);
gvar_set ("last_time", ticks);
float delta_time = gvar_get ("delta_time");
/* We pin the camera to the player position, with eye level 20
centimeters below the height. */
glm_vec3_copy (player_entity->position, camera_position);
+6 -7
View File
@@ -1,7 +1,6 @@
#include "uiman.h"
extern SDL_Window *sdl_window;
extern int sdl_window_w, sdl_window_h;
/* UI global state variables. */
@@ -19,10 +18,10 @@ void
uiman_init ()
{
ui_widget_mesh_init ();
glm_ortho (0.0, sdl_window_w, sdl_window_h, 0.0, -1.0, 1.0, projection);
glm_ortho (0.0, gvar_get ("window_width"), gvar_get ("window_height"), 0.0, -1.0, 1.0, projection);
ui_root = Widget_new ();
IVEC2_SETI (ui_root->size, sdl_window_w, sdl_window_h);
IVEC2_SETI (ui_root->size, gvar_get ("window_width"), gvar_get ("window_height"));
scm_c_primitive_load ("res/scripts/global/ui_styles.scm");
scm_c_primitive_load ("res/scripts/global/ui_composites.scm");
@@ -45,8 +44,8 @@ uiman_tick ()
void
uiman_render ()
{
Widget_render (ui_root, projection, sdl_window_h);
Widget_render (tooltip_widget, projection, sdl_window_h);
Widget_render (ui_root, projection, gvar_get ("window_height"));
Widget_render (tooltip_widget, projection, gvar_get ("window_height"));
}
void
@@ -120,8 +119,8 @@ gboolean
uiman_cb_window_resize (SDL_Event *event, void *data)
{
UNUSED (event, data);
glm_ortho (0.0, sdl_window_w, sdl_window_h, 0.0, -1.0, 1.0, projection);
IVEC2_SETI (ui_root->size, sdl_window_w, sdl_window_h);
glm_ortho (0.0, gvar_get ("window_width"), gvar_get ("window_height"), 0.0, -1.0, 1.0, projection);
IVEC2_SETI (ui_root->size, gvar_get ("window_width"), gvar_get ("window_height"));
return FALSE;
}
+40 -19
View File
@@ -235,6 +235,22 @@ _wgcb_event (Widget *w, SDL_Event *event, void *data)
}
}
static inline TextAlignment
_str_to_textalignment (const char *str)
{
if (!g_strcmp0 (str, "center"))
{
return TEXT_ALIGN_CENTER;
}
if (!g_strcmp0 (str, "right"))
{
return TEXT_ALIGN_RIGHT;
}
return TEXT_ALIGN_LEFT;
}
static void
_wgg_set_property (Widget *w, const char *key, SCM val)
{
@@ -345,24 +361,39 @@ _wgg_set_property (Widget *w, const char *key, SCM val)
switch (w->kind)
{
case WIDGET_LABEL:
g_string_overwrite (w->label.text, 0, scm_to_utf8_string (val));
g_string_assign (w->label.text, scm_to_utf8_string (val));
break;
case WIDGET_MULTILINE_TEXT:
g_string_overwrite (w->multiline_text.text, 0, scm_to_utf8_string (val));
g_string_assign (w->multiline_text.text, scm_to_utf8_string (val));
break;
case WIDGET_WINDOW:
g_string_overwrite (w->window.title, 0, scm_to_utf8_string (val));
g_string_assign (w->window.title, scm_to_utf8_string (val));
break;
case WIDGET_ENTRY:
g_string_overwrite (w->entry.ghost_text, 0, scm_to_utf8_string (val));
g_string_assign (w->entry.ghost_text, scm_to_utf8_string (val));
default:
break;
}
}
if (!g_strcmp0 (key, "text-alignment"))
{
const char *s = scm_symbol_to_string (val) ? scm_to_utf8_string (scm_symbol_to_string (val)) : NULL;
if (s != NULL && w->kind == WIDGET_LABEL)
{
w->label.text_alignment = _str_to_textalignment (s);
}
if (s != NULL && w->kind == WIDGET_MULTILINE_TEXT)
{
w->multiline_text.text_alignment = _str_to_textalignment (s);
}
}
if (!g_strcmp0 (key, "tooltip"))
{
g_string_overwrite (w->tooltip, 0, scm_to_utf8_string (val));
g_string_assign (w->tooltip, scm_to_utf8_string (val));
}
if (!g_strcmp0 (key, "on-tick"))
@@ -470,14 +501,6 @@ _wg_set_icon (SCM widget_ptr, SCM icon_val)
return SCM_UNSPECIFIED;
}
static SCM
_wg_get_child (SCM widget_ptr, SCM index_val)
{
Widget *w = (Widget *) scm_to_pointer (widget_ptr);
int index = scm_to_int (index_val);
return scm_from_pointer (g_array_index (w->children, Widget *, index), NULL);
}
static SCM
_wg_set_text (SCM widget_ptr, SCM val)
{
@@ -486,16 +509,16 @@ _wg_set_text (SCM widget_ptr, SCM val)
switch (w->kind)
{
case WIDGET_LABEL:
g_string_overwrite (w->label.text, 0, scm_to_utf8_string (val));
g_string_assign (w->label.text, scm_to_utf8_string (val));
break;
case WIDGET_MULTILINE_TEXT:
g_string_overwrite (w->multiline_text.text, 0, scm_to_utf8_string (val));
g_string_assign (w->multiline_text.text, scm_to_utf8_string (val));
break;
case WIDGET_WINDOW:
g_string_overwrite (w->window.title, 0, scm_to_utf8_string (val));
g_string_assign (w->window.title, scm_to_utf8_string (val));
break;
case WIDGET_ENTRY:
g_string_overwrite (w->entry.ghost_text, 0, scm_to_utf8_string (val));
g_string_assign (w->entry.ghost_text, scm_to_utf8_string (val));
default:
break;
}
@@ -512,7 +535,5 @@ widget_guile_register ()
scm_c_define_gsubr ("widget-get-icon", 1, 0, 0, _wg_get_icon);
scm_c_define_gsubr ("widget-set-icon!", 2, 0, 0, _wg_set_icon);
scm_c_define_gsubr ("widget-get-child", 2, 0, 0, _wg_get_child);
scm_c_define_gsubr ("widget-set-text!", 2, 0, 0, _wg_set_text);
}