From 84df81bd033ede182a8a0c5d851caa2f55b8c093 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 15 Sep 2023 14:01:58 +0900 Subject: [PATCH] [ruamoko] Clean up buttons and axes Reloading progs (or shutting down) needs to clean up the buttons otherwise the input system will have issues when it cleans up because the buttons and axes have ceased to exist. --- libs/ruamoko/rua_input.c | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index df86bcec1..5aea4630a 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -37,6 +37,8 @@ #endif #include "QF/cmem.h" +#include "QF/darray.h" +#include "QF/fbsearch.h" #include "QF/hash.h" #include "QF/input.h" #include "QF/progs.h" @@ -50,10 +52,14 @@ typedef struct rua_in_cookie_s { pr_ptr_t data; } rua_in_cookie_t; +typedef struct DARRAY_TYPE (pr_ptr_t) ptrset_t; + typedef struct input_resources_s { hashctx_t *hashctx; hashtab_t *cookies; memsuper_t *cookie_super; + ptrset_t buttons; + ptrset_t axes; } input_resources_t; static void @@ -138,9 +144,30 @@ bi_IN_ClearStates (progs_t *pr, void *_res) IN_ClearStates (); } +static int +ptrcmp (const void *a, const void *b) +{ + pr_ptr_t ptra = *(const pr_ptr_t *) a; + pr_ptr_t ptrb = *(const pr_ptr_t *) b; + return ptra - ptrb; +} + +static void +bi_add_pointer (ptrset_t *pointers, pr_ptr_t ptr) +{ + size_t ind = pointers->size; + if (ind && ptr < pointers->a[ind - 1]) { + pr_ptr_t *p = fbsearch (&ptr, pointers->a, ind, sizeof (pr_ptr_t), + ptrcmp); + ind = p ? p - pointers->a + 1 : 0; + } + DARRAY_INSERT_AT (pointers, ptr, ind); +} + static void bi_IN_CreateButton (progs_t *pr, void *_res) { + input_resources_t *res = _res; const char *name = P_GSTRING (pr, 0); const char *desc = P_GSTRING (pr, 1); in_button_t *button = PR_Zone_Malloc (pr, sizeof (in_button_t)); @@ -148,11 +175,14 @@ bi_IN_CreateButton (progs_t *pr, void *_res) button->description = desc; IN_RegisterButton (button); RETURN_POINTER (pr, button); + + bi_add_pointer (&res->buttons, R_POINTER (pr)); } static void bi_IN_CreateAxis (progs_t *pr, void *_res) { + input_resources_t *res = _res; const char *name = P_GSTRING (pr, 0); const char *desc = P_GSTRING (pr, 1); in_axis_t *axis = PR_Zone_Malloc (pr, sizeof (in_axis_t)); @@ -160,6 +190,8 @@ bi_IN_CreateAxis (progs_t *pr, void *_res) axis->description = desc; IN_RegisterAxis (axis); RETURN_POINTER (pr, axis); + + bi_add_pointer (&res->axes, R_POINTER (pr)); } static void @@ -478,14 +510,41 @@ bi_input_clear (progs_t *pr, void *_res) { input_resources_t *res = _res; Hash_FlushTable (res->cookies); + + for (size_t i = 0; i < res->buttons.size; i++) { + auto button = (in_button_t *) PR_GetPointer (pr, res->buttons.a[i]); + if (button->listeners) { + for (size_t j = 0; j < button->listeners->size; j++) { + rua_in_cookie_t *cookie = button->listeners->a[j].ldata; + release_cookie (pr, res, cookie); + } + } + IN_UnregisterButton (button); + } + res->buttons.size = 0; + + for (size_t i = 0; i < res->axes.size; i++) { + auto axis = (in_axis_t *) PR_GetPointer (pr, res->axes.a[i]); + if (axis->listeners) { + for (size_t j = 0; j < axis->listeners->size; j++) { + rua_in_cookie_t *cookie = axis->listeners->a[j].ldata; + release_cookie (pr, res, cookie); + } + } + IN_UnregisterAxis (axis); + } + res->axes.size = 0; } static void bi_input_destroy (progs_t *pr, void *_res) { input_resources_t *res = _res; + bi_input_clear (pr, res); Hash_DelTable (res->cookies); delete_memsuper (res->cookie_super); + DARRAY_CLEAR (&res->buttons); + DARRAY_CLEAR (&res->axes); free (res); } @@ -519,6 +578,8 @@ RUA_Input_Init (progs_t *pr, int secure) input_resources_t *res = calloc (sizeof (input_resources_t), 1); res->cookie_super = new_memsuper (); + res->buttons = (ptrset_t) DARRAY_STATIC_INIT (16); + res->axes = (ptrset_t) DARRAY_STATIC_INIT (16); res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, pr->hashctx); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies);