More guile integration

This commit is contained in:
2025-07-20 16:31:02 +02:00
parent e708f319f3
commit 009b12da5d
14 changed files with 495 additions and 417 deletions
+78
View File
@@ -0,0 +1,78 @@
(define COLOR_TRANSPARENT '(0.0 0.0 0.0 0.0))
(define COLOR_WHITE '(1.0 1.0 1.0 1.0))
(define COLOR_BLACK '(0.0 0.0 0.0 1.0))
(define style-default
(style-new #:text-color COLOR_WHITE
#:text-color-hovered COLOR_WHITE
#:text-color-clicked COLOR_WHITE
#:ghost-text-color '(1.0 1.0 1.0 0.5)
#:icon-color COLOR_WHITE
#:icon-color-hovered COLOR_WHITE
#:icon-color-clicked COLOR_WHITE
#:scrollbar-color COLOR_WHITE
#:scrollbar-color-hovered COLOR_WHITE
#:scrollbar-color-clicked COLOR_WHITE
#:border-color COLOR_WHITE
#:progress-color COLOR_WHITE
#:resize-handle-color COLOR_WHITE))
(define style-window
(style-new #:background-color '(0.2 0.2 0.2 1.0)
#:background-color-hovered '(0.2 0.2 0.2 1.0)
#:background-color-clicked '(0.3 0.3 0.3 1.0)
#:text-color COLOR_WHITE
#:text-color-hovered COLOR_WHITE
#:text-color-clicked COLOR_WHITE
#:border-color '(0.5 0.5 0.5 1.0)
#:resize-handle-color COLOR_WHITE
#:border-width 3))
(define style-container
(style-new #:background-color '(0.3 0.3 0.3 1.0)
#:background-color-hovered '(0.3 0.3 0.3 1.0)
#:background-color-clicked '(0.3 0.3 0.3 1.0)
#:border-color '(0.4 0.4 0.4 1.0)
#:border-width 2))
(define style-icon-button
(style-new #:icon-color COLOR_WHITE
#:icon-color-hovered '(1.0 1.0 0.0 1.0)
#:icon-color-clicked '(1.0 0.0 0.0 1.0)))
(define (widget-checkbox-icon-switch widget event)
(if (= (widget-get-icon widget) 1)
(widget-set-icon! widget 2)
(widget-set-icon! widget 1)))
;; The function is evaulated and returns a pointer, the game eats it
;; and adds it to the UI root. Boom.
(define (widget-checkbox text flag . args)
(apply
widget-new
(append
(list 'container #:horizontal #t #:layout-spacing 8)
args
(list
(widget-new 'plain #:style style-icon-button #:icon 1 #:aspect-ratio 1
#:on-click (lambda (w e) (widget-checkbox-icon-switch w e) (flags-switch flag)))
(widget-new 'label #:style style-default #:text text #:layout-weight 1)))))
(widget-new
'window
#:style style-window
#:text "Debug window"
#:w 350
#:layout-padding 8
#:vertical #f
#:horizontal #t
;; The rest is children.
(widget-new
'flowbox
#:style style-container
#:layout-padding 8
#:layout-spacing 8
#:horizontal #t
(widget-checkbox "Flight" "flight_enabled" #:layout-weight 0.5 #:h 20)
(widget-checkbox "Wireframe" "wireframe_enabled" #:layout-weight 0.5 #:h 20)))
+37 -4
View File
@@ -8,20 +8,53 @@ flags_init ()
flags = g_hash_table_new (g_str_hash, g_str_equal);
}
static SCM
_scm_flags_set (SCM flag_scm, SCM val_scm)
{
const char *flag = scm_to_utf8_string (flag_scm);
gboolean val = scm_is_true (val_scm);
flags_set (flag, val);
return SCM_UNSPECIFIED;
}
static SCM
_scm_flags_get (SCM flag_scm)
{
const char *flag = scm_to_utf8_string (flag_scm);
gboolean val = flags_get (flag);
return val ? SCM_BOOL_T : SCM_BOOL_F;
}
static SCM
_scm_flags_switch (SCM flag_scm)
{
const char *flag = scm_to_utf8_string (flag_scm);
flags_switch (flag);
return SCM_UNSPECIFIED;
}
void
flags_switch (char *flag)
flags_guile_register ()
{
scm_c_define_gsubr("flags-set", 2, 0, 0, _scm_flags_set);
scm_c_define_gsubr("flags-get", 1, 0, 0, _scm_flags_get);
scm_c_define_gsubr("flags-switch", 1, 0, 0, _scm_flags_switch);
}
void
flags_switch (const char *flag)
{
flags_set (flag, !flags_get (flag));
}
void
flags_set (char *flag, gboolean value)
flags_set (const char *flag, gboolean value)
{
g_hash_table_replace (flags, flag, GINT_TO_POINTER (value));
g_hash_table_replace (flags, g_strdup (flag), GINT_TO_POINTER (value));
}
gboolean
flags_get (char *flag)
flags_get (const char *flag)
{
return GPOINTER_TO_INT (g_hash_table_lookup (flags, flag));
}
+5 -3
View File
@@ -1,6 +1,7 @@
#pragma once
#include <glib-2.0/glib.h>
#include <libguile.h>
/*
@@ -23,6 +24,7 @@
*/
void flags_init ();
void flags_switch (char *flag);
void flags_set (char *flag, gboolean value);
gboolean flags_get (char *flag);
void flags_guile_register ();
void flags_switch (const char *flag);
void flags_set (const char *flag, gboolean value);
gboolean flags_get (const char *flag);
+1
View File
@@ -20,6 +20,7 @@ SDL_AppInit (void **appstate, int argc, char **argv)
SDL_SetAppMetadata (GAME_NAME, GAME_VERSION, "eur.chopininteractive.wschod-game");
scm_init_guile ();
flags_guile_register ();
widget_guile_register ();
graphics_init ();
+6 -9
View File
@@ -3,14 +3,6 @@
extern SDL_Window *sdl_window;
extern int sdl_window_w, sdl_window_h;
/* Not really required for the functioning of the UI system. */
extern float delta_time;
extern int n_frame_ents;
extern int n_frame_chunks;
extern int render_distance;
extern vec3 camera_position;
/* UI global state variables. */
static Widget *ui_root;
@@ -29,8 +21,13 @@ uiman_init ()
ui_widget_mesh_init ();
glm_ortho (0.0, sdl_window_w, sdl_window_h, 0.0, -1.0, 1.0, projection);
ui_root = Widget_plain_new ();
ui_root = Widget_new ();
IVEC2_SETI (ui_root->size, sdl_window_w, sdl_window_h);
SCM scm_debug = scm_c_primitive_load ("res/ui/debug_window.scm");
Widget *debug_window = (Widget *) scm_to_pointer (scm_debug);
Widget_add_child (ui_root, debug_window);
Widget_dump (ui_root, 0);
}
void
+2 -1
View File
@@ -1,7 +1,8 @@
#pragma once
#include <libguile.h>
#include "widget_core.h"
#include "widget_composites.h"
#include "../flags.h"
#include "../state.h"
#include "../camera.h"
-63
View File
@@ -1,63 +0,0 @@
#include "widget_composites.h"
Widget *
Widget_label_make_int (const char *fmt, int *ptr, TextAlignment alignment)
{
Widget *w = Widget_label_new (NULL, alignment);
Widget_set_on_event (w, EVENT_TICK, uicb_widget_op, WidgetOpData_new (OP_LABEL_SHOW_INT, ptr, fmt));
return w;
}
Widget *
Widget_label_make_float (const char *fmt, float *ptr, TextAlignment alignment)
{
Widget *w = Widget_label_new (NULL, alignment);
Widget_set_on_event (w, EVENT_TICK, uicb_widget_op, WidgetOpData_new (OP_LABEL_SHOW_FLOAT, ptr, fmt));
return w;
}
Widget *
Widget_composite_spinner_make_int (const char *fmt, int *ptr)
{
Widget *cont = Widget_container_new (TRUE);
Widget *left = Widget_plain_new ();
Widget *label = Widget_label_make_int (fmt, ptr, TEXT_ALIGN_CENTER);
Widget *right = Widget_plain_new ();
left->style = WSTYLE (STYLE_ICON_BUTTON);
right->style = WSTYLE (STYLE_ICON_BUTTON);
Widget_set_on_event (left, EVENT_LEFT_UP, uicb_widget_op, WidgetOpData_new (OP_MODIFY_INT, ptr, -1.0));
left->icon = ICON_MINUS;
left->aspect_ratio = 1.0;
Widget_set_on_event (right, EVENT_LEFT_UP, uicb_widget_op, WidgetOpData_new (OP_MODIFY_INT, ptr, 1.0));
right->icon = ICON_PLUS;
right->aspect_ratio = 1.0;
cont->layout_spacing = 8;
Widget_add_child_weighed (cont, left, 1);
Widget_add_child_weighed (cont, label, 1);
Widget_add_child_weighed (cont, right, 1);
return cont;
}
Widget *
Widget_composite_checkbox_make (const char *label, char *flag)
{
Widget *cont = Widget_container_new (TRUE);
Widget *box = Widget_plain_new ();
box->style = WSTYLE (STYLE_ICON_BUTTON);
box->icon = ICON_CHECKBOX_UNCHECKED;
box->aspect_ratio = 1.0;
Widget_set_on_event (box, EVENT_TICK, uicb_widget_op, WidgetOpData_new (OP_CHECKBOX_SHOW_FLAG, flag));
Widget_set_on_event (box, EVENT_LEFT_UP, uicb_widget_op, WidgetOpData_new (OP_SWITCH_FLAG, flag));
cont->layout_spacing = 8;
Widget_add_child_weighed (cont, box, 1);
Widget_add_child_weighed (cont, Widget_label_new (label, TEXT_ALIGN_LEFT), 1);
return cont;
}
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include "widget_fw.h"
#include "widget_core.h"
#include "widget_ops.h"
Widget *Widget_label_make_int (const char *fmt, int *ptr, TextAlignment alignment);
Widget *Widget_label_make_float (const char *fmt, float *ptr, TextAlignment alignment);
Widget *Widget_composite_spinner_make_int (const char *format, int *ptr);
Widget *Widget_composite_checkbox_make (const char *label, char *flag);
Widget *Widget_composite_window_make (const char *title);
+10 -166
View File
@@ -1,145 +1,14 @@
#include "widget_core.h"
static const Widget DEFAULT_WIDGET =
{
.kind = WIDGET_PLAIN,
.do_layout = NULL,
.do_render = Widget_render_base,
.visible = true,
.layout_dirty = true,
.children = NULL,
.icon = ICON_NONE
};
static inline Widget *
_uiel_new (WidgetKind kind)
{
/* new0 instead of new is important, otherwise there's trash memory
in the function pointers */
Widget *e = g_new0 (Widget, 1);
*e = DEFAULT_WIDGET;
e->kind = kind;
e->children = g_array_new (false, false, sizeof (Widget *));
e->style = WSTYLE (STYLE_DEFAULT);
return e;
}
Widget *
Widget_plain_new ()
{
return _uiel_new (WIDGET_PLAIN);
}
Widget *
Widget_label_new (const char *text, TextAlignment alignment)
Widget_new ()
{
Widget *e = _uiel_new (WIDGET_LABEL);
e->do_render = Widget_render_label;
e->label.text = g_string_new (text);
e->label.text_alignment = alignment;
return e;
}
Widget *
Widget_scrollbar_new (Widget *target, gboolean horizontal)
{
Widget *e = _uiel_new (WIDGET_SCROLLBAR);
e->do_render = Widget_render_scrollbar;
e->scrollbar.target = target;
e->scrollbar.horizontal = horizontal;
e->on_event[EVENT_LEFT_DOWN] = uicb_scrollbar_start_scroll;
e->on_event[EVENT_MOUSE_MOVE] = uicb_scrollbar_scroll;
e->on_event[EVENT_LEFT_UP] = uicb_scrollbar_stop_scroll;
Widget_set_on_event (e, EVENT_SCROLL_UP, uicb_widget_op, WidgetOpData_new (OP_SCROLLABLE_SCROLL, target, SCROLL_UP));
Widget_set_on_event (e, EVENT_SCROLL_DOWN, uicb_widget_op, WidgetOpData_new (OP_SCROLLABLE_SCROLL, target, SCROLL_DOWN));
return e;
}
Widget *
Widget_progress_new (gboolean horizontal, float min, float max, float *ptr)
{
Widget *e = _uiel_new (WIDGET_SCROLLBAR);
e->do_render = Widget_render_progress;
e->progress.horizontal = horizontal;
e->progress.min = min;
e->progress.max = max;
e->progress.ptr = ptr;
return e;
}
Widget *
Widget_multiline_text_new (const char *text, int line_height, TextAlignment alignment)
{
Widget *e = _uiel_new (WIDGET_MULTILINE_TEXT);
e->do_layout = Widget_layout_multiline_text;
e->do_render = Widget_render_multiline_text;
e->multiline_text.text = g_string_new (text);
e->multiline_text.lines = g_array_new (FALSE, FALSE, sizeof (GString));
e->multiline_text.line_height = line_height;
e->multiline_text.text_alignment = alignment;
return e;
}
Widget *
Widget_entry_new (const char *ghost_text)
{
Widget *e = _uiel_new (WIDGET_ENTRY);
e->do_render = Widget_render_entry;
e->entry.ghost_text = g_string_new (ghost_text);
e->entry.content = g_string_new (NULL);
Widget_set_on_event (e, EVENT_FOCUS_GAINED, uicb_widget_op, WidgetOpData_new (OP_START_TEXT_INPUT, NULL));
Widget_set_on_event (e, EVENT_FOCUS_LOST, uicb_widget_op, WidgetOpData_new (OP_STOP_TEXT_INPUT, NULL));
Widget_set_on_event (e, EVENT_TEXT_INPUT, uicb_widget_op, WidgetOpData_new (OP_ENTRY_INPUT_TEXT, NULL));
Widget_set_on_key (e, SDL_SCANCODE_BACKSPACE, uicb_widget_op, WidgetOpData_new (OP_ENTRY_DELETE_BACKWARD, NULL));
Widget_set_on_key (e, SDL_SCANCODE_DELETE, uicb_widget_op, WidgetOpData_new (OP_ENTRY_DELETE_FORWARD, NULL));
Widget_set_on_key (e, SDL_SCANCODE_LEFT, uicb_widget_op, WidgetOpData_new (OP_ENTRY_MOVE_LEFT, NULL));
Widget_set_on_key (e, SDL_SCANCODE_RIGHT, uicb_widget_op, WidgetOpData_new (OP_ENTRY_MOVE_RIGHT, NULL));
return e;
}
Widget *
Widget_container_new (gboolean horizontal)
{
Widget *e = _uiel_new (WIDGET_CONTAINER);
e->do_layout = Widget_layout_container;
e->container.horizontal = horizontal;
return e;
}
Widget *
Widget_scrollable_new ()
{
Widget *e = _uiel_new (WIDGET_SCROLLABLE);
e->do_layout = Widget_layout_scrollable;
e->scrollable.scroll_amount = 10;
Widget_set_on_event (e, EVENT_SCROLL_UP, uicb_widget_op, WidgetOpData_new (OP_SCROLLABLE_SCROLL, e, SCROLL_UP));
Widget_set_on_event (e, EVENT_SCROLL_DOWN, uicb_widget_op, WidgetOpData_new (OP_SCROLLABLE_SCROLL, e, SCROLL_DOWN));
return e;
}
Widget *
Widget_flowbox_new (gboolean horizontal)
{
Widget *e = _uiel_new (WIDGET_FLOWBOX);
e->do_layout = Widget_layout_flowbox;
e->flowbox.horizontal = horizontal;
return e;
}
Widget *
Widget_window_new (const char *title, int titlebar_height)
{
Widget *e = _uiel_new (WIDGET_WINDOW);
e->window.title = g_string_new (title);
e->window.titlebar_height = titlebar_height;
e->window.resizable_h = TRUE;
e->window.resizable_v = TRUE;
e->do_layout = Widget_layout_window;
e->do_render = Widget_render_window;
e->on_event[EVENT_LEFT_DOWN] = uicb_window_start_drag;
e->on_event[EVENT_MOUSE_MOVE] = uicb_window_drag;
e->on_event[EVENT_LEFT_UP] = uicb_window_stop_drag;
return e;
Widget *w = g_new0 (Widget, 1);
w->children = g_array_new (false, false, sizeof (Widget *));
w->style = g_new0 (WidgetStyle, 1);
w->visible = TRUE;
w->do_render = Widget_render_base;
return w;
}
void
@@ -155,20 +24,6 @@ Widget_add_child (Widget *parent, Widget *child)
g_array_append_val (parent->children, child);
}
void
Widget_add_child_weighed (Widget *parent, Widget *child, float layout_weight)
{
child->layout_weight = layout_weight;
Widget_add_child (parent, child);
}
void Widget_add_child_flowbox (Widget *parent, Widget *child,
float layout_weight, int cross_axis_size)
{
child->size[parent->flowbox.horizontal ? 1 : 0] = cross_axis_size;
Widget_add_child_weighed (parent, child, layout_weight);
}
void
Widget_set_on_event (Widget *widget, WidgetEvent event,
void (*on_event) (Widget *, SDL_Event *, void *),
@@ -186,12 +41,6 @@ Widget_set_on_key (Widget *widget, SDL_Scancode key,
widget->key_data[key] = userdata;
}
void
Widget_label_set_text (Widget *widget, const char *text)
{
g_string_overwrite (widget->label.text, 0, text);
}
void
Widget_label_printf (Widget *widget, const char *format, ...)
{
@@ -201,13 +50,6 @@ Widget_label_printf (Widget *widget, const char *format, ...)
va_end (args);
}
void
Widget_multiline_text_set_text (Widget *widget, const char *text)
{
g_string_overwrite (widget->multiline_text.text, 0, text);
widget->layout_dirty = TRUE;
}
void
Widget_entry_input_text (Widget *widget, const char *text)
{
@@ -379,7 +221,9 @@ Widget_free (Widget *widget)
{
if (widget->on_event[ev] && widget->event_data[ev])
{
g_free (widget->event_data[ev]);
/* TODO: add ownership data to the Widget to determine
whether we allocated that, or Guile did. */
/* g_free (widget->event_data[ev]); */
}
}
+1 -17
View File
@@ -189,31 +189,15 @@ typedef struct Widget
void *key_data[SDL_SCANCODE_COUNT];
} Widget;
Widget *Widget_plain_new ();
Widget *Widget_label_new (const char *text, TextAlignment alignment);
Widget *Widget_scrollbar_new (Widget *target, gboolean horizontal);
Widget *Widget_progress_new (gboolean horizontal, float min, float max, float *ptr);
Widget *Widget_multiline_text_new (const char *text, int line_height, TextAlignment alignment);
Widget *Widget_entry_new (const char *ghost_text);
Widget *Widget_container_new (gboolean horizontal);
Widget *Widget_scrollable_new ();
Widget *Widget_flowbox_new (gboolean horizontal);
Widget *Widget_window_new (const char *title, int titlebar_height);
Widget *Widget_new ();
void Widget_add_child (Widget *parent, Widget *child);
void Widget_add_child_weighed (Widget *parent, Widget *child,
float layout_weight);
void Widget_add_child_flowbox (Widget *parent, Widget *child,
float layout_weight, int cross_axis_size);
void Widget_set_on_event (Widget *widget, WidgetEvent event, void (*on_event) (Widget *, SDL_Event *, void *), void *userdata);
void Widget_set_on_key (Widget *widget, SDL_Scancode key, void (*on_key) (Widget *, SDL_Event *, void *), void *userdata);
void Widget_label_set_text (Widget *widget, const char *text);
void Widget_label_printf (Widget *widget, const char *format, ...);
void Widget_multiline_text_set_text (Widget *widget, const char *text);
void Widget_entry_input_text (Widget *widget, const char *text);
void Widget_scrollable_scroll (Widget *widget, ivec2 direction);
+355 -29
View File
@@ -1,69 +1,369 @@
#include "widget_guile.h"
/* Widget styles */
void
scm_vec4_to_float_array(SCM val, float out[4])
{
if (scm_is_pair (val)) {
for (int i = 0; i < 4; ++i)
{
if (!scm_is_pair (val))
{
scm_misc_error ("scm_vec4_to_float_array", "Expected list of 4 values", SCM_EOL);
}
out[i] = (float) scm_to_double (scm_car(val));
val = scm_cdr (val);
}
if (!scm_is_null (val))
{
scm_misc_error ("scm_vec4_to_float_array", "List must have exactly 4 values", SCM_EOL);
}
}
else
{
scm_wrong_type_arg ("scm_vec4_to_float_array", 0, val);
}
}
static SCM
_wg_style_new (SCM args)
{
WidgetStyle *s = g_new0 (WidgetStyle, 1);
while (scm_is_pair (args))
{
SCM key = scm_car (args);
args = scm_cdr (args);
SCM val = scm_car (args);
args = scm_cdr (args);
const char *k = scm_to_utf8_string (scm_symbol_to_string (scm_keyword_to_symbol (key)));
if (!strcmp (k, "background-color"))
{
scm_vec4_to_float_array (val, s->background_color);
}
if (!strcmp (k, "background-color-hovered"))
{
scm_vec4_to_float_array (val, s->background_color_hovered);
}
if (!strcmp (k, "background-color-clicked"))
{
scm_vec4_to_float_array (val, s->background_color_clicked);
}
if (!strcmp (k, "text-color"))
{
scm_vec4_to_float_array (val, s->text_color);
}
if (!strcmp (k, "text-color-hovered"))
{
scm_vec4_to_float_array (val, s->text_color_hovered);
}
if (!strcmp (k, "text-color-clicked"))
{
scm_vec4_to_float_array (val, s->text_color_clicked);
}
if (!strcmp (k, "ghost-text-color"))
{
scm_vec4_to_float_array (val, s->ghost_text_color);
}
if (!strcmp (k, "icon-color"))
{
scm_vec4_to_float_array (val, s->icon_color);
}
if (!strcmp (k, "icon-color-hovered"))
{
scm_vec4_to_float_array (val, s->icon_color_hovered);
}
if (!strcmp (k, "icon-color-clicked"))
{
scm_vec4_to_float_array (val, s->icon_color_clicked);
}
if (!strcmp (k, "scrollbar-color"))
{
scm_vec4_to_float_array (val, s->scrollbar_color);
}
if (!strcmp (k, "scrollbar-color-hovered"))
{
scm_vec4_to_float_array (val, s->scrollbar_color_hovered);
}
if (!strcmp (k, "scrollbar-color-clicked"))
{
scm_vec4_to_float_array (val, s->scrollbar_color_clicked);
}
if (!strcmp (k, "border-color"))
{
scm_vec4_to_float_array (val, s->border_color);
}
if (!strcmp (k, "progress-color"))
{
scm_vec4_to_float_array (val, s->progress_color);
}
if (!strcmp (k, "resize-handle-color"))
{
scm_vec4_to_float_array (val, s->resize_handle_color);
}
if (!strcmp (k, "border-width"))
{
s->border_width = scm_to_int (val);
}
}
return scm_from_pointer (s, NULL);
}
/* Widgets */
static Widget *
_wgg_build (const char *type)
{
Widget *e = g_new0 (Widget, 1);
e->children = g_array_new (false, false, sizeof (Widget *));
e->style = WSTYLE (STYLE_DEFAULT);
Widget *w = Widget_new ();
if (g_strcmp0 (type, "plain") == 0)
if (!g_strcmp0 (type, "plain"))
{
e->kind = WIDGET_PLAIN;
w->kind = WIDGET_PLAIN;
}
if (g_strcmp0 (type, "label") == 0)
if (!g_strcmp0 (type, "label"))
{
e->kind = WIDGET_LABEL;
w->kind = WIDGET_LABEL;
w->do_render = Widget_render_label;
w->label.text = g_string_new (NULL);
}
if (g_strcmp0 (type, "scrollbar") == 0)
if (!g_strcmp0 (type, "scrollbar"))
{
e->kind = WIDGET_SCROLLBAR;
w->kind = WIDGET_SCROLLBAR;
w->do_render = Widget_render_scrollbar;
}
if (g_strcmp0 (type, "progress") == 0)
if (!g_strcmp0 (type, "progress"))
{
e->kind = WIDGET_PROGRESS;
w->kind = WIDGET_PROGRESS;
w->do_render = Widget_render_progress;
}
if (g_strcmp0 (type, "entry") == 0)
if (!g_strcmp0 (type, "entry"))
{
e->kind = WIDGET_ENTRY;
w->kind = WIDGET_ENTRY;
w->do_render = Widget_render_entry;
}
if (g_strcmp0 (type, "multiline") == 0)
if (!g_strcmp0 (type, "multiline"))
{
e->kind = WIDGET_MULTILINE_TEXT;
w->kind = WIDGET_MULTILINE_TEXT;
w->do_render = Widget_render_multiline_text;
w->multiline_text.text = g_string_new (NULL);
w->multiline_text.lines = g_array_new (FALSE, FALSE, sizeof (GString));
}
if (g_strcmp0 (type, "container") == 0)
if (!g_strcmp0 (type, "container"))
{
e->kind = WIDGET_CONTAINER;
w->kind = WIDGET_CONTAINER;
w->do_layout = Widget_layout_container;
}
if (g_strcmp0 (type, "scrollable") == 0)
if (!g_strcmp0 (type, "scrollable"))
{
e->kind = WIDGET_SCROLLABLE;
w->kind = WIDGET_SCROLLABLE;
w->do_layout = Widget_layout_scrollable;
}
if (g_strcmp0 (type, "flowbox") == 0)
if (!g_strcmp0 (type, "flowbox"))
{
e->kind = WIDGET_FLOWBOX;
w->kind = WIDGET_FLOWBOX;
w->do_layout = Widget_layout_flowbox;
}
if (g_strcmp0 (type, "window") == 0)
if (!g_strcmp0 (type, "window"))
{
e->kind = WIDGET_WINDOW;
w->kind = WIDGET_WINDOW;
w->do_render = Widget_render_window;
w->do_layout = Widget_layout_window;
w->window.title = g_string_new ("Window");
w->window.titlebar_height = 20;
w->on_event[EVENT_LEFT_DOWN] = uicb_window_start_drag;
w->on_event[EVENT_MOUSE_MOVE] = uicb_window_drag;
w->on_event[EVENT_LEFT_UP] = uicb_window_stop_drag;
}
return NULL;
return w;
}
void
_wgcb_event (Widget *w, SDL_Event *event, void *data)
{
SCM proc = (SCM) data;
if (scm_is_true (scm_procedure_p (proc)))
{
scm_call_2 (proc, scm_from_pointer (w, NULL), scm_from_pointer (event, NULL));
}
}
static void
_wgg_set_property (Widget *w, const char *key, SCM val)
{
UNUSED (w, key, val);
if (!g_strcmp0 (key, "visible"))
{
w->visible = scm_is_true (val);
}
if (!g_strcmp0 (key, "x"))
{
w->position[0] = scm_to_int (val);
}
if (!g_strcmp0 (key, "y"))
{
w->position[1] = scm_to_int (val);
}
if (!g_strcmp0 (key, "w"))
{
w->size[0] = scm_to_int (val);
}
if (!g_strcmp0 (key, "h"))
{
w->size[1] = scm_to_int (val);
}
if (!g_strcmp0 (key, "layout-padding"))
{
w->layout_padding = scm_to_int (val);
}
if (!g_strcmp0 (key, "layout-spacing"))
{
w->layout_spacing = scm_to_int (val);
}
if (!g_strcmp0 (key, "layout-weight"))
{
w->layout_weight = scm_to_double (val);
}
if (!g_strcmp0 (key, "horizontal"))
{
switch (w->kind)
{
case WIDGET_SCROLLBAR:
w->scrollbar.horizontal = scm_is_true (val);
break;
case WIDGET_PROGRESS:
w->progress.horizontal = scm_is_true (val);
break;
case WIDGET_CONTAINER:
w->container.horizontal = scm_is_true (val);
break;
case WIDGET_SCROLLABLE:
w->scrollable.layout_horizontal = scm_is_true (val);
break;
case WIDGET_FLOWBOX:
w->flowbox.horizontal = scm_is_true (val);
break;
case WIDGET_WINDOW:
w->window.resizable_h = scm_is_true (val);
default:
break;
}
}
if (!g_strcmp0 (key, "vertical") && w->kind == WIDGET_WINDOW)
{
switch (w->kind)
{
case WIDGET_WINDOW:
w->window.resizable_v = scm_is_true (val);
break;
case WIDGET_SCROLLABLE:
w->window.resizable_v = scm_is_true (val);
default:
break;
}
}
if (!g_strcmp0 (key, "aspect-ratio"))
{
w->aspect_ratio = scm_to_double (val);
}
if (!g_strcmp0 (key, "line-height") && w->kind == WIDGET_MULTILINE_TEXT)
{
w->multiline_text.line_height = scm_to_int (val);
}
if (!g_strcmp0 (key, "style"))
{
w->style = (const WidgetStyle *) scm_to_pointer (val);
}
if (!g_strcmp0 (key, "icon"))
{
w->icon = scm_to_int (val);
}
if (!g_strcmp0 (key, "text"))
{
switch (w->kind)
{
case WIDGET_LABEL:
g_string_overwrite (w->label.text, 0, scm_to_utf8_string (val));
break;
case WIDGET_MULTILINE_TEXT:
g_string_overwrite (w->multiline_text.text, 0, scm_to_utf8_string (val));
break;
case WIDGET_WINDOW:
g_string_overwrite (w->window.title, 0, scm_to_utf8_string (val));
default:
break;
}
}
if (!g_strcmp0 (key, "on-tick"))
{
if (!scm_is_true (scm_procedure_p (val)))
{
scm_misc_error ("widget-set-property", "Expected a procedure for on-tick", scm_list_1 (val));
}
w->on_event[EVENT_TICK] = _wgcb_event;
w->event_data[EVENT_TICK] = (void *) val;
scm_gc_protect_object (val);
}
if (!g_strcmp0 (key, "on-click"))
{
if (!scm_is_true (scm_procedure_p (val)))
{
scm_misc_error ("widget-set-property", "Expected a procedure for on-tick", scm_list_1 (val));
}
w->on_event[EVENT_LEFT_UP] = _wgcb_event;
w->event_data[EVENT_LEFT_UP] = (void *) val;
scm_gc_protect_object (val);
}
}
// (widget-new TYPE #:PROP1 VALUE1 ... #:PROPN VALUEN child1 ... childn)
@@ -79,6 +379,7 @@ _wg_widget_new (SCM args)
args = scm_cdr (args);
const char *type = scm_symbol_to_string (type_sym) ? scm_to_utf8_string (scm_symbol_to_string (type_sym)) : NULL;
if (!type)
{
scm_misc_error ("widget-new", "Invalid widget type symbol", SCM_EOL);
@@ -91,28 +392,33 @@ _wg_widget_new (SCM args)
scm_misc_error ("widget-new", "Unknown widget type", scm_list_1 (type_sym));
}
// Parse keyword args
/* Parse props */
while (scm_is_pair (args))
{
SCM key = scm_car (args);
args = scm_cdr (args);
if (!scm_is_keyword (key))
{
break;
}
args = scm_cdr (args);
if (!scm_is_pair (args))
{
scm_misc_error ("widget-new", "Expected value after keyword", SCM_EOL);
}
SCM val = scm_car (args);
args = scm_cdr (args);
_wgg_set_property (w, scm_to_utf8_string (scm_keyword_to_symbol (key)), val);
SCM sym = scm_keyword_to_symbol (key);
SCM str_obj = scm_symbol_to_string (sym);
const char *key_cstr = scm_to_utf8_string (str_obj);
_wgg_set_property (w, key_cstr, val);
}
// Remaining args = children
/* Parse the children of the widget. */
while (scm_is_pair (args))
{
SCM child = scm_car (args);
@@ -124,8 +430,28 @@ _wg_widget_new (SCM args)
return scm_from_pointer (w, NULL);
}
static SCM
_wg_get_icon (SCM widget_ptr)
{
Widget *w = (Widget *) scm_to_pointer (widget_ptr);
return scm_from_int (w->icon);
}
static SCM
_wg_set_icon (SCM widget_ptr, SCM icon_val)
{
Widget *w = (Widget *) scm_to_pointer (widget_ptr);
int icon = scm_to_int (icon_val);
w->icon = icon;
return SCM_UNSPECIFIED;
}
void
widget_guile_register ()
{
scm_c_define_gsubr ("widget-new", 0, 0, 1, _wg_widget_new);
scm_c_define_gsubr ("style-new", 0, 0, 1, _wg_style_new);
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);
}
-22
View File
@@ -14,13 +14,6 @@ WidgetOpData_new (WidgetOp op, void *ptr, ...)
switch (data->op)
{
case OP_LABEL_SHOW_INT:
case OP_LABEL_SHOW_FLOAT:
data->fmt = va_arg (ap, const char *);
break;
case OP_MODIFY_INT:
data->delta = (float) va_arg (ap, double);
break;
case OP_SCROLLABLE_SCROLL:
glm_ivec2_copy (va_arg (ap, int *), data->scroll_dir);
break;
@@ -40,21 +33,6 @@ uicb_widget_op (Widget *self, SDL_Event *sdl_event, void *userdata)
switch (data->op)
{
case OP_SWITCH_FLAG:
flags_switch ((char *) data->ptr);
break;
case OP_LABEL_SHOW_INT:
Widget_label_printf (self, data->fmt, * (int *)data->ptr);
break;
case OP_LABEL_SHOW_FLOAT:
Widget_label_printf (self, data->fmt, * (float *)data->ptr);
break;
case OP_CHECKBOX_SHOW_FLAG:
self->icon = flags_get ((char *) data->ptr) ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX_UNCHECKED;
break;
case OP_MODIFY_INT:
*(int*) data->ptr += (int) data->delta;
break;
case OP_SCROLLABLE_SCROLL:
Widget_scrollable_scroll ((Widget *) data->ptr, data->scroll_dir);
break;
-11
View File
@@ -7,14 +7,6 @@
typedef enum WidgetOp
{
OP_SWITCH_FLAG,
OP_MODIFY_INT,
OP_LABEL_SHOW_INT,
OP_LABEL_SHOW_FLOAT,
OP_CHECKBOX_SHOW_FLAG,
OP_SCROLLABLE_SCROLL,
OP_START_TEXT_INPUT,
@@ -31,9 +23,6 @@ typedef struct WidgetOpData
WidgetOp op;
void *ptr;
/* These are used dependant on what you wanna do. */
const char *fmt;
float delta;
ivec2 scroll_dir;
} WidgetOpData;
-79
View File
@@ -2,10 +2,6 @@
#include <cglm/cglm.h>
#define COLOR_TRANSPARENT { 0.0, 0.0, 0.0, 0.0 }
#define COLOR_BLACK { 0.0, 0.0, 0.0, 1.0 }
#define COLOR_WHITE { 1.0, 1.0, 1.0, 1.0 }
typedef struct WidgetStyle
{
vec4 background_color;
@@ -33,78 +29,3 @@ typedef struct WidgetStyle
unsigned int background_image;
} WidgetStyle;
typedef enum WidgetStyleId
{
STYLE_DEFAULT,
STYLE_TOOLTIP,
STYLE_ICON_BUTTON,
STYLE_WINDOW,
STYLE_CONTAINER,
NSTYLES
} WidgetStyleId;
static const WidgetStyle widget_styles[NSTYLES] = {
[STYLE_DEFAULT] = {
.text_color = COLOR_WHITE,
.text_color_hovered = COLOR_WHITE,
.text_color_clicked = COLOR_WHITE,
.ghost_text_color = { 1.0, 1.0, 1.0, 0.5 },
.icon_color = COLOR_WHITE,
.icon_color_hovered = COLOR_WHITE,
.icon_color_clicked = COLOR_WHITE,
.scrollbar_color = COLOR_WHITE,
.scrollbar_color_hovered = COLOR_WHITE,
.scrollbar_color_clicked = COLOR_WHITE,
.border_color = COLOR_WHITE,
.progress_color = COLOR_WHITE,
.resize_handle_color = { 0.6, 0.6, 0.6, 1.0 },
.border_width = 0,
},
[STYLE_TOOLTIP] = {
.background_color = { 0.1, 0.1, 0.1, 1.0 },
.background_color_hovered = { 0.1, 0.1, 0.1, 1.0 },
.background_color_clicked = { 0.1, 0.1, 0.1, 1.0 },
.text_color = COLOR_WHITE,
.text_color_hovered = COLOR_WHITE,
.text_color_clicked = COLOR_WHITE,
},
[STYLE_ICON_BUTTON] = {
.icon_color = COLOR_WHITE,
.icon_color_hovered = { 1.0, 1.0, 0.0, 1.0 },
.icon_color_clicked = { 1.0, 0.0, 0.0, 1.0 },
},
[STYLE_WINDOW] = {
.background_color = { 0.2, 0.2, 0.2, 1.0 },
.background_color_hovered = { 0.2, 0.2, 0.2, 1.0 },
.background_color_clicked = { 0.3, 0.3, 0.3, 1.0 },
.text_color = COLOR_WHITE,
.text_color_hovered = COLOR_WHITE,
.text_color_clicked = COLOR_WHITE,
.border_color = { 0.5, 0.5, 0.5, 1.0 },
.resize_handle_color = COLOR_WHITE,
.border_width = 3,
},
[STYLE_CONTAINER] = {
.background_color = { 0.3, 0.3, 0.3, 1.0 },
.background_color_hovered = { 0.3, 0.3, 0.3, 1.0 },
.background_color_clicked = { 0.3, 0.3, 0.3, 1.0 },
.border_color = { 0.4, 0.4, 0.4, 1.0 },
.border_width = 2,
},
};
#define WSTYLE(id) (&widget_styles[id])