More changes to UI code

This commit is contained in:
2025-07-20 17:21:38 +02:00
parent 009b12da5d
commit feba432ea8
9 changed files with 176 additions and 229 deletions
@@ -74,5 +74,5 @@
#: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)))
(widget-checkbox "Flight" "flight_enabled" #:layout-weight 0.5 #:h 20 #:tooltip "Testt")
(widget-checkbox "Wireframe" "wireframe_enabled" #:layout-weight 0.5 #:h 20 #:tooltip "test222")))
+22
View File
@@ -0,0 +1,22 @@
(define COLOR_WHITE '(1.0 1.0 1.0 1.0))
(define COLOR_BLACK '(0.0 0.0 0.0 1.0))
(define style-tooltip
(style-new
#:background-color COLOR_BLACK))
(define style-tooltip-text
(style-new
#:text-color COLOR_WHITE
#:text-color-hovered COLOR_WHITE
#:text-color-clicked COLOR_WHITE))
(widget-new
'flowbox
#:style style-tooltip
#:w 200
#:visible #f
#:horizontal #t
#:layout-padding 4
#:layout-spacing 8
(widget-new 'multiline #:line-height 20 #:layout-weight 1 #:style style-tooltip-text))
+15 -11
View File
@@ -12,8 +12,8 @@ static Widget *hovered_widget = NULL;
static Widget *clicked_widget = NULL;
static Widget *focused_widget = NULL;
/* static Widget *tooltip_widget = NULL; */
/* static Widget *tooltip_text = NULL; */
static Widget *tooltip_widget = NULL;
static Widget *tooltip_text = NULL;
void
uiman_init ()
@@ -24,10 +24,13 @@ uiman_init ()
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");
SCM scm_debug = scm_c_primitive_load ("res/scripts/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);
SCM scm_tooltip = scm_c_primitive_load ("res/scripts/ui/tooltip.scm");
tooltip_widget = (Widget *) scm_to_pointer (scm_tooltip);
tooltip_text = g_array_index (tooltip_widget->children, Widget *, 0);
}
void
@@ -40,7 +43,7 @@ void
uiman_render ()
{
Widget_render (ui_root, projection, sdl_window_h);
/* Widget_render (tooltip_widget, projection, sdl_window_h); */
Widget_render (tooltip_widget, projection, sdl_window_h);
}
void
@@ -95,7 +98,8 @@ uiman_cb_switch_focus (SDL_Event *event, void *data)
flags_switch ("ui_has_focus");
SDL_SetWindowRelativeMouseMode (sdl_window, !flags_get ("ui_has_focus"));
/* We reset the global states of the UI. */
/* We reset the global states of the UI. TODO: also launch the
callbacks on mouse leave? */
SDL_StopTextInput (sdl_window);
_uiman_set_hovered (hovered_widget, FALSE);
hovered_widget = NULL;
@@ -104,7 +108,7 @@ uiman_cb_switch_focus (SDL_Event *event, void *data)
_uiman_set_clicked (clicked_widget, FALSE);
clicked_widget = NULL;
/* tooltip_widget->visible = FALSE; */
tooltip_widget->visible = FALSE;
return TRUE;
}
@@ -171,13 +175,13 @@ uiman_cb_mouse_motion (SDL_Event *event, void *data)
if (tooltip_source && tooltip_source->tooltip && tooltip_source->tooltip->len > 0)
{
/* Widget_multiline_text_set_text (tooltip_text, tooltip_source->tooltip->str); */
/* tooltip_widget->visible = TRUE; */
/* IVEC2_SETI (tooltip_widget->position, pos[0] + 12, pos[1] + 12); */
g_string_overwrite (tooltip_text->multiline_text.text, 0, tooltip_source->tooltip->str);
tooltip_widget->visible = TRUE;
IVEC2_SETI (tooltip_widget->position, pos[0] + 12, pos[1] + 12);
}
else
{
/* tooltip_widget->visible = FALSE; */
tooltip_widget->visible = FALSE;
}
/* This callback always eats the event, because why would the game
@@ -1,97 +1,105 @@
#include "widget_ops.h"
#include "widget_boilerplate.h"
extern SDL_Window *sdl_window;
WidgetOpData *
WidgetOpData_new (WidgetOp op, void *ptr, ...)
/* Entry boilerplate */
void
ui_boilerplate_entry_move_left (Widget *self, SDL_Event *sdl_event, void *userdata)
{
WidgetOpData *data = g_new0 (WidgetOpData, 1);
data->op = op;
data->ptr = ptr;
va_list ap;
va_start (ap, ptr);
switch (data->op)
{
case OP_SCROLLABLE_SCROLL:
glm_ivec2_copy (va_arg (ap, int *), data->scroll_dir);
break;
default:
break;
}
UNUSED (sdl_event, userdata);
va_end (ap);
return data;
if (self->entry.cursor_position > 0)
{
self->entry.cursor_position--;
}
}
void
uicb_widget_op (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_entry_move_right (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event);
WidgetOpData *data = userdata;
switch (data->op)
UNUSED (sdl_event, userdata);
if (self->entry.cursor_position < g_utf8_strlen (self->entry.content->str, -1))
{
case OP_SCROLLABLE_SCROLL:
Widget_scrollable_scroll ((Widget *) data->ptr, data->scroll_dir);
break;
case OP_START_TEXT_INPUT:
SDL_StartTextInput (sdl_window);
break;
case OP_STOP_TEXT_INPUT:
SDL_StopTextInput (sdl_window);
break;
case OP_ENTRY_INPUT_TEXT:
Widget_entry_input_text (self, sdl_event->text.text);
break;
case OP_ENTRY_DELETE_BACKWARD:
if (self->entry.cursor_position > 0
&& self->entry.content->len > 0)
{
gchar *start = g_utf8_offset_to_pointer (self->entry.content->str, self->entry.cursor_position - 1);
gchar *end = g_utf8_next_char (start);
gint byte_offset = start - self->entry.content->str;
gint byte_len = end - start;
g_string_erase (self->entry.content, byte_offset, byte_len);
self->entry.cursor_position--;
}
break;
case OP_ENTRY_DELETE_FORWARD:
int total_chars = g_utf8_strlen (self->entry.content->str, -1);
if (self->entry.cursor_position < total_chars)
{
gchar *start = g_utf8_offset_to_pointer (self->entry.content->str, self->entry.cursor_position);
gchar *end = g_utf8_next_char (start);
gint byte_offset = start - self->entry.content->str;
gint byte_len = end - start;
g_string_erase (self->entry.content, byte_offset, byte_len);
}
break;
case OP_ENTRY_MOVE_LEFT:
if (self->entry.cursor_position > 0)
{
self->entry.cursor_position--;
}
break;
case OP_ENTRY_MOVE_RIGHT:
if (self->entry.cursor_position < g_utf8_strlen (self->entry.content->str, -1))
{
self->entry.cursor_position++;
}
break;
default:
break;
self->entry.cursor_position++;
}
}
void
ui_boilerplate_entry_delete_backward (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event, userdata);
if (self->entry.cursor_position > 0
&& self->entry.content->len > 0)
{
gchar *start = g_utf8_offset_to_pointer (self->entry.content->str, self->entry.cursor_position - 1);
gchar *end = g_utf8_next_char (start);
gint byte_offset = start - self->entry.content->str;
gint byte_len = end - start;
g_string_erase (self->entry.content, byte_offset, byte_len);
self->entry.cursor_position--;
}
}
void
ui_boilerplate_entry_delete_forward (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event, userdata);
int total_chars = g_utf8_strlen (self->entry.content->str, -1);
if (self->entry.cursor_position < total_chars)
{
gchar *start = g_utf8_offset_to_pointer (self->entry.content->str, self->entry.cursor_position);
gchar *end = g_utf8_next_char (start);
gint byte_offset = start - self->entry.content->str;
gint byte_len = end - start;
g_string_erase (self->entry.content, byte_offset, byte_len);
}
}
void
ui_boilerplate_entry_input_text (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (userdata);
Widget_entry_input_text (self, sdl_event->text.text);
}
void
ui_boilerplate_entry_start_input (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (self, sdl_event, userdata);
SDL_StartTextInput (sdl_window);
}
void
ui_boilerplate_entry_stop_input (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (self, sdl_event, userdata);
SDL_StopTextInput (sdl_window);
}
/* Scrollbar boilerplate. */
void
uicb_scrollbar_start_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_scrollbar_scroll_up (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event, userdata);
Widget_scrollable_scroll (self->scrollbar.target, SCROLL_UP);
}
void
ui_boilerplate_scrollbar_scroll_down (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event, userdata);
Widget_scrollable_scroll (self->scrollbar.target, SCROLL_DOWN);
}
void
ui_boilerplate_scrollbar_start_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (userdata);
@@ -123,7 +131,7 @@ uicb_scrollbar_start_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
}
void
uicb_scrollbar_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_scrollbar_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (userdata);
@@ -154,7 +162,7 @@ uicb_scrollbar_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
}
void
uicb_scrollbar_stop_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_scrollbar_stop_scroll (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event, userdata);
self->scrollbar.dragging = FALSE;
@@ -174,7 +182,7 @@ ui_window_is_in_resize_area (Widget *self, vec2 mouse_pos)
}
void
uicb_window_start_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_window_start_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (userdata);
@@ -195,21 +203,21 @@ uicb_window_start_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
}
void
_uicb_window_move (Widget *self, ivec2 mouse_pos)
_ui_boilerplate_window_move (Widget *self, ivec2 mouse_pos)
{
self->position[0] = mouse_pos[0] - self->window.drag_offset[0];
self->position[1] = mouse_pos[1] - self->window.drag_offset[1];
}
void
_uicb_window_resize (Widget *self, ivec2 mouse_pos)
_ui_boilerplate_window_resize (Widget *self, ivec2 mouse_pos)
{
self->size[0] = mouse_pos[0] - self->position[0];
self->size[1] = mouse_pos[1] - self->position[1];
}
void
uicb_window_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_window_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (userdata);
@@ -217,18 +225,18 @@ uicb_window_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
if (self->window.moving)
{
_uicb_window_move (self, mouse_pos);
_ui_boilerplate_window_move (self, mouse_pos);
self->layout_dirty = TRUE;
}
else if (self->window.resizing)
{
_uicb_window_resize (self, mouse_pos);
_ui_boilerplate_window_resize (self, mouse_pos);
self->layout_dirty = TRUE;
}
}
void
uicb_window_stop_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
ui_boilerplate_window_stop_drag (Widget *self, SDL_Event *sdl_event, void *userdata)
{
UNUSED (sdl_event, userdata);
self->window.moving = FALSE;
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <SDL3/SDL.h>
#include "widget_fw.h"
#include "widget_core.h"
void ui_boilerplate_entry_start_input (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_entry_stop_input (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_scrollbar_scroll_up (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_scrollbar_scroll_down (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_scrollbar_start_scroll (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_scrollbar_scroll (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_scrollbar_stop_scroll (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_window_start_drag (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_window_drag (Widget *self, SDL_Event *sdl_event, void *userdata);
void ui_boilerplate_window_stop_drag (Widget *self, SDL_Event *sdl_event, void *userdata);
+1 -73
View File
@@ -5,6 +5,7 @@ Widget_new ()
{
Widget *w = g_new0 (Widget, 1);
w->children = g_array_new (false, false, sizeof (Widget *));
w->tooltip = g_string_new (NULL);
w->style = g_new0 (WidgetStyle, 1);
w->visible = TRUE;
w->do_render = Widget_render_base;
@@ -24,32 +25,6 @@ Widget_add_child (Widget *parent, Widget *child)
g_array_append_val (parent->children, child);
}
void
Widget_set_on_event (Widget *widget, WidgetEvent event,
void (*on_event) (Widget *, SDL_Event *, void *),
void *userdata)
{
widget->on_event[event] = on_event;
widget->event_data[event] = userdata;
}
void
Widget_set_on_key (Widget *widget, SDL_Scancode key,
void (*on_key) (Widget *, SDL_Event *, void *), void *userdata)
{
widget->on_key[key] = on_key;
widget->key_data[key] = userdata;
}
void
Widget_label_printf (Widget *widget, const char *format, ...)
{
va_list args;
va_start (args, format);
g_string_vprintf (widget->label.text, format, args);
va_end (args);
}
void
Widget_entry_input_text (Widget *widget, const char *text)
{
@@ -92,27 +67,6 @@ Widget_hit_test (Widget *widget, ivec2 point)
&& y >= top && y <= bottom);
}
gboolean
wcond_tooltip (Widget *widget, void *userdata)
{
UNUSED (userdata);
return widget->tooltip != NULL;
}
gboolean
wcond_event (Widget *widget, void *event)
{
WidgetEvent e = GPOINTER_TO_INT (event);
return widget->on_event[e] != NULL;
}
gboolean
wcond_any (Widget *widget, void *userdata)
{
UNUSED (widget, userdata);
return TRUE;
}
Widget *
Widget_find_xy_cond (Widget *widget, ivec2 pos, gboolean (*cond_func) (Widget *, void *), void *userdata)
{
@@ -230,29 +184,3 @@ Widget_free (Widget *widget)
g_free (widget);
}
void
Widget_dump (Widget *widget, int depth)
{
if (!widget) return;
GString *prefix = g_string_new (NULL);
for (int i = 0; i < depth; ++i)
{
g_string_append (prefix, " ");
}
g_debug ("%sWidget %p kind=%d visible=%d", prefix->str, widget, widget->kind, widget->visible);
for (int i = 0; i < EVENT_COUNT; ++i)
{
if (widget->on_event[i])
{
g_debug ("%s Has handler for event %d", prefix->str, i);
}
}
WFOREACH (widget, child)
{
Widget_dump (child, depth + 1);
}
}
+7 -15
View File
@@ -7,7 +7,7 @@
#include "widget_render.h"
#include "widget_layout.h"
#include "widget_style.h"
#include "widget_ops.h"
#include "widget_boilerplate.h"
#include "../util.h"
#include "../resources.h"
@@ -19,8 +19,8 @@
for (unsigned int _i = 0; _i < (widget)->children->len; ++_i) \
for (Widget *child = g_array_index ((widget)->children, Widget *, _i); child; child = NULL)
#define SCROLL_UP (vec2) { 0.0, -1.0 }
#define SCROLL_DOWN (vec2) { 0.0, 1.0 }
#define SCROLL_UP (ivec2) { 0, -1 }
#define SCROLL_DOWN (ivec2) { 0, 1 }
typedef enum WidgetKind
{
@@ -190,25 +190,17 @@ typedef struct Widget
} Widget;
Widget *Widget_new ();
void Widget_add_child (Widget *parent, Widget *child);
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_printf (Widget *widget, const char *format, ...);
void Widget_entry_input_text (Widget *widget, const char *text);
void Widget_scrollable_scroll (Widget *widget, ivec2 direction);
gboolean wcond_tooltip (Widget *widget, void *userdata);
gboolean wcond_event (Widget *widget, void *event);
gboolean wcond_any (Widget *widget, void *userdata);
static inline gboolean wcond_tooltip (Widget *widget, void *userdata) { UNUSED (userdata); return widget->tooltip != NULL; }
static inline gboolean wcond_event (Widget *widget, void *event) { WidgetEvent e = GPOINTER_TO_INT (event); return widget->on_event[e] != NULL; }
static inline gboolean wcond_any (Widget *widget, void *userdata) { UNUSED (widget, userdata); return TRUE; }
Widget *Widget_find_xy_cond (Widget *widget, ivec2 point, gboolean (*cond_func) (Widget *, void *), void *userdata);
void Widget_tick (Widget *widget);
void Widget_render (Widget *widget, mat4 projection, int window_height);
void Widget_free (Widget *widget);
void Widget_dump (Widget *widget, int depth);
+14 -3
View File
@@ -154,6 +154,11 @@ _wgg_build (const char *type)
{
w->kind = WIDGET_SCROLLBAR;
w->do_render = Widget_render_scrollbar;
w->on_event[EVENT_LEFT_DOWN] = ui_boilerplate_scrollbar_start_scroll;
w->on_event[EVENT_MOUSE_MOVE] = ui_boilerplate_scrollbar_scroll;
w->on_event[EVENT_LEFT_UP] = ui_boilerplate_scrollbar_stop_scroll;
w->on_event[EVENT_SCROLL_UP] = ui_boilerplate_scrollbar_scroll_up;
w->on_event[EVENT_SCROLL_DOWN] = ui_boilerplate_scrollbar_scroll_down;
}
if (!g_strcmp0 (type, "progress"))
@@ -172,6 +177,7 @@ _wgg_build (const char *type)
{
w->kind = WIDGET_MULTILINE_TEXT;
w->do_render = Widget_render_multiline_text;
w->do_layout = Widget_layout_multiline_text;
w->multiline_text.text = g_string_new (NULL);
w->multiline_text.lines = g_array_new (FALSE, FALSE, sizeof (GString));
}
@@ -201,9 +207,9 @@ _wgg_build (const char *type)
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;
w->on_event[EVENT_LEFT_DOWN] = ui_boilerplate_window_start_drag;
w->on_event[EVENT_MOUSE_MOVE] = ui_boilerplate_window_drag;
w->on_event[EVENT_LEFT_UP] = ui_boilerplate_window_stop_drag;
}
return w;
@@ -341,6 +347,11 @@ _wgg_set_property (Widget *w, const char *key, SCM val)
}
}
if (!g_strcmp0 (key, "tooltip"))
{
g_string_overwrite (w->tooltip, 0, scm_to_utf8_string (val));
}
if (!g_strcmp0 (key, "on-tick"))
{
if (!scm_is_true (scm_procedure_p (val)))
-38
View File
@@ -1,38 +0,0 @@
#pragma once
#include <SDL3/SDL.h>
#include "widget_fw.h"
#include "widget_core.h"
typedef enum WidgetOp
{
OP_SCROLLABLE_SCROLL,
OP_START_TEXT_INPUT,
OP_STOP_TEXT_INPUT,
OP_ENTRY_INPUT_TEXT,
OP_ENTRY_DELETE_BACKWARD,
OP_ENTRY_DELETE_FORWARD,
OP_ENTRY_MOVE_LEFT,
OP_ENTRY_MOVE_RIGHT
} WidgetOp;
typedef struct WidgetOpData
{
WidgetOp op;
void *ptr;
ivec2 scroll_dir;
} WidgetOpData;
WidgetOpData *WidgetOpData_new (WidgetOp op, void *ptr, ...);
void uicb_widget_op (Widget *self, SDL_Event *sdl_event, void *userdata);
void uicb_scrollbar_start_scroll (Widget *self, SDL_Event *sdl_event, void *userdata);
void uicb_scrollbar_scroll (Widget *self, SDL_Event *sdl_event, void *userdata);
void uicb_scrollbar_stop_scroll (Widget *self, SDL_Event *sdl_event, void *userdata);
void uicb_window_start_drag (Widget *self, SDL_Event *sdl_event, void *userdata);
void uicb_window_drag (Widget *self, SDL_Event *sdl_event, void *userdata);
void uicb_window_stop_drag (Widget *self, SDL_Event *sdl_event, void *userdata);