From 6b2bd02b14e25bf9a3f1514317ec0d2c202446f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 31 Dec 2023 14:09:43 +0900 Subject: [PATCH] [ui] Add a canvas reference component It's used for finding the entity that has the actual canvas component attached. Useful for sharing a single canvas between multiple view hierarchies, and worked as a proof of concept for doing similar with hierarchy references, and might work for properly destroying canvas items (fills etc) when a view entity is deleted (if attached to every view). --- include/QF/ui/canvas.h | 26 +++++++++++++++++++++-- libs/ui/canvas.c | 48 +++++++++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index f4f5a9712..091b3465d 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -52,9 +52,11 @@ enum { // last so deleting an entity removes the grouped components first // also, does not have a subpool - canvas_canvas, + canvas_canvasref, // reference to entity with canvas + canvas_canvas, // actual canvas object - canvas_comp_count + canvas_comp_count, + canvas_subpool_count = canvas_canvasref }; typedef struct canvas_s { @@ -99,6 +101,9 @@ void Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, void Canvas_SetLen (canvas_system_t canvas_sys, uint32_t ent, view_pos_t len); CANVASINLINE view_t Canvas_GetRootView (canvas_system_t canvas_sys, uint32_t ent); +CANVASINLINE uint32_t Canvas_Entity (canvas_system_t canvas_sys, uint32_t ent); +CANVASINLINE void Canvas_SetReference (canvas_system_t canvas_sys, + uint32_t ent, uint32_t ref); CANVASINLINE bool *Canvas_Visible (canvas_system_t canvas_sys, uint32_t ent); CANVASINLINE int32_t *Canvas_DrawGroup (canvas_system_t canvas_sys, uint32_t ent); @@ -121,6 +126,23 @@ Canvas_GetRootView (canvas_system_t canvas_sys, uint32_t ent) return View_FromEntity (viewsys, ent); } +CANVASINLINE +uint32_t +Canvas_Entity (canvas_system_t canvas_sys, uint32_t ent) +{ + uint32_t rcomp = canvas_sys.base + canvas_canvasref; + return *(uint32_t *) Ent_GetComponent (ent, rcomp, canvas_sys.reg); +} + +CANVASINLINE +void +Canvas_SetReference (canvas_system_t canvas_sys, uint32_t ent, uint32_t ref) +{ + uint32_t rcomp = canvas_sys.base + canvas_canvasref; + Ent_SetComponent (ent, rcomp, canvas_sys.reg, &ref); +} + + CANVASINLINE bool * Canvas_Visible (canvas_system_t canvas_sys, uint32_t ent) diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 2e16e0ef3..0c07e7b93 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -42,13 +42,15 @@ static uint32_t _canvas_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp, uint32_t c) { - comp += canvas_canvas - c; + uint32_t rcomp = comp - c + canvas_canvasref; + uint32_t ccomp = comp - c + canvas_canvas; // view components come immediately after canvas components - uint32_t vcomp = view_href + comp + canvas_comp_count - canvas_canvas; + uint32_t vcomp = view_href + canvas_comp_count + comp - c; hierref_t *href = Ent_GetComponent (ent, vcomp, reg); - // the root entity of the hierarchy has the canvas component + // the root entity of the hierarchy has the canvasref or canvas component uint32_t cent = href->hierarchy->ent[0]; - canvas_t *canvas = Ent_GetComponent (cent, comp, reg); + cent = *(uint32_t *) Ent_GetComponent (cent, rcomp, reg); + canvas_t *canvas = Ent_GetComponent (cent, ccomp, reg); return canvas->range[c]; } @@ -79,7 +81,7 @@ canvas_canvas_destroy (void *_canvas) { canvas_t *canvas = _canvas; auto reg = canvas->reg; - for (uint32_t i = 0; i < canvas_canvas; i++) { + for (uint32_t i = 0; i < canvas_subpool_count; i++) { ECS_DelSubpoolRange (reg, canvas->base + i, canvas->range[i]); } } @@ -155,6 +157,11 @@ const component_t canvas_components[canvas_comp_count] = { .name = "outline", .rangeid = canvas_outline_rangeid, }, + + [canvas_canvasref] = { + .size = sizeof (uint32_t), + .name = "canvasref", + }, [canvas_canvas] = { .size = sizeof (canvas_t), .name = "canvas", @@ -162,6 +169,9 @@ const component_t canvas_components[canvas_comp_count] = { }, }; +#define c_canvasref (canvas_sys.base + canvas_canvasref) +#define c_canvas (canvas_sys.base + canvas_canvas) + typedef void (*canvas_sysfunc_f) (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range); static void @@ -471,8 +481,7 @@ Canvas_Draw (canvas_system_t canvas_sys) }; auto reg = canvas_sys.reg; - uint32_t comp = canvas_sys.base + canvas_canvas; - ecs_pool_t *canvas_pool = ®->comp_pools[comp]; + ecs_pool_t *canvas_pool = ®->comp_pools[c_canvas]; uint32_t count = canvas_pool->count; uint32_t *entities = canvas_pool->dense; __auto_type canvases = (canvas_t *) canvas_pool->data; @@ -535,15 +544,19 @@ Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent) .base = canvas_sys.base, .visible = true }; - for (uint32_t i = 0; i < canvas_canvas; i++) { + for (uint32_t i = 0; i < canvas_subpool_count; i++) { canvas.range[i] = ECS_NewSubpoolRange (canvas_sys.reg, canvas_sys.base + i); } - Ent_SetComponent (ent, canvas_sys.base + canvas_canvas, canvas_sys.reg, - &canvas); - View_AddToEntity (ent, - (ecs_system_t) { canvas_sys.reg, canvas_sys.view_base }, - nullview); + // add a self reference to keep _canvas_rangeid and Canvas_Entity simple + Ent_SetComponent (ent, c_canvasref, canvas_sys.reg, &ent); + Ent_SetComponent (ent, c_canvas, canvas_sys.reg, &canvas); + if (!Ent_HasComponent (ent, canvas_sys.view_base + view_href, + canvas_sys.reg)) { + View_AddToEntity (ent, (ecs_system_t) { canvas_sys.reg, + canvas_sys.view_base }, + nullview); + } } uint32_t @@ -575,8 +588,7 @@ void Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, uint32_t component) { - canvas_t *canvas = Ent_GetComponent (ent, canvas_sys.base + canvas_canvas, - canvas_sys.reg); + canvas_t *canvas = Ent_GetComponent (ent, c_canvas, canvas_sys.reg); uint32_t rid = canvas->range[component]; uint32_t c = component + canvas_sys.base; ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, c, rid); @@ -597,9 +609,8 @@ canvas_draw_cmp (const void *_a, const void *_b, void *arg) { uint32_t enta = *(const uint32_t *)_a; uint32_t entb = *(const uint32_t *)_b; - canvas_system_t *canvas_sys = arg; - auto reg = canvas_sys->reg; - uint32_t c_canvas = canvas_sys->base + canvas_canvas; + auto canvas_sys = *(canvas_system_t *)arg; + auto reg = canvas_sys.reg; auto canvasa = (canvas_t *) Ent_GetComponent (enta, c_canvas, reg); auto canvasb = (canvas_t *) Ent_GetComponent (entb, c_canvas, reg); int diff = canvasa->draw_group - canvasb->draw_group; @@ -618,6 +629,5 @@ void Canvas_DrawSort (canvas_system_t canvas_sys) { auto reg = canvas_sys.reg; - uint32_t c_canvas = canvas_sys.base + canvas_canvas; ECS_SortComponentPool (reg, c_canvas, canvas_draw_cmp, &canvas_sys); }