2022-12-20 10:45:48 +00:00
|
|
|
/*
|
|
|
|
canvas.c
|
|
|
|
|
|
|
|
Integration of 2d and 3d objects
|
|
|
|
|
|
|
|
Copyright (C) 2022 Bill Currie
|
|
|
|
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
Date: 2022/12/12
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2023-01-20 06:57:29 +00:00
|
|
|
#define IMPLEMENT_CANVAS_Funcs
|
2022-12-20 10:45:48 +00:00
|
|
|
#include "QF/ui/canvas.h"
|
2023-07-04 15:40:29 +00:00
|
|
|
#include "QF/ui/imui.h"
|
2022-12-20 10:45:48 +00:00
|
|
|
#include "QF/ui/text.h"
|
|
|
|
#include "QF/ui/view.h"
|
|
|
|
|
|
|
|
#include "QF/plugin/vid_render.h"
|
|
|
|
|
2023-01-20 18:26:02 +00:00
|
|
|
static uint32_t
|
|
|
|
_canvas_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp, uint32_t c)
|
|
|
|
{
|
|
|
|
comp += canvas_canvas - c;
|
|
|
|
// view components come immediately after canvas components
|
|
|
|
uint32_t vcomp = view_href + comp + canvas_comp_count - canvas_canvas;
|
|
|
|
hierref_t *href = Ent_GetComponent (ent, vcomp, reg);
|
|
|
|
// the root entity of the hierarchy has the canvas component
|
|
|
|
uint32_t cent = href->hierarchy->ent[0];
|
|
|
|
canvas_t *canvas = Ent_GetComponent (cent, comp, reg);
|
|
|
|
return canvas->range[c];
|
|
|
|
}
|
|
|
|
|
2022-12-20 10:45:48 +00:00
|
|
|
#define canvas_rangeid(c) \
|
|
|
|
static uint32_t \
|
|
|
|
canvas_##c##_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp) \
|
|
|
|
{ \
|
2023-01-20 18:26:02 +00:00
|
|
|
return _canvas_rangeid (reg, ent, comp, canvas_##c); \
|
2022-12-20 10:45:48 +00:00
|
|
|
}
|
|
|
|
canvas_rangeid(update)
|
|
|
|
canvas_rangeid(updateonce)
|
|
|
|
canvas_rangeid(tile)
|
|
|
|
canvas_rangeid(pic)
|
2023-01-17 02:33:47 +00:00
|
|
|
canvas_rangeid(fitpic)
|
2022-12-20 10:45:48 +00:00
|
|
|
canvas_rangeid(subpic)
|
|
|
|
canvas_rangeid(cachepic)
|
|
|
|
canvas_rangeid(fill)
|
|
|
|
canvas_rangeid(charbuff)
|
2023-07-01 10:49:49 +00:00
|
|
|
canvas_rangeid(passage_glyphs)
|
|
|
|
canvas_rangeid(glyphs)
|
2022-12-20 10:45:48 +00:00
|
|
|
canvas_rangeid(func)
|
2023-01-21 18:43:58 +00:00
|
|
|
canvas_rangeid(lateupdate)
|
2022-12-20 10:45:48 +00:00
|
|
|
canvas_rangeid(outline)
|
|
|
|
#undef canvas_rangeid
|
|
|
|
|
|
|
|
static void
|
|
|
|
canvas_canvas_destroy (void *_canvas)
|
|
|
|
{
|
2023-07-09 03:06:08 +00:00
|
|
|
canvas_t *canvas = _canvas;
|
|
|
|
auto reg = canvas->reg;
|
2023-07-09 13:14:02 +00:00
|
|
|
for (uint32_t i = 0; i < canvas_canvas; i++) {
|
2023-07-09 03:06:08 +00:00
|
|
|
ECS_DelSubpoolRange (reg, canvas->base + i, canvas->range[i]);
|
|
|
|
}
|
2022-12-20 10:45:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const component_t canvas_components[canvas_comp_count] = {
|
|
|
|
[canvas_update] = {
|
|
|
|
.size = sizeof (canvas_update_f),
|
|
|
|
.name = "update",
|
|
|
|
.rangeid = canvas_update_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_updateonce] = {
|
|
|
|
.size = sizeof (canvas_update_f),
|
|
|
|
.name = "updateonce",
|
|
|
|
.rangeid = canvas_updateonce_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_tile] = {
|
|
|
|
.size = sizeof (byte),
|
2023-01-17 02:33:47 +00:00
|
|
|
.name = "tile",
|
2022-12-20 10:45:48 +00:00
|
|
|
.rangeid = canvas_tile_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_pic] = {
|
|
|
|
.size = sizeof (qpic_t *),
|
|
|
|
.name = "pic",
|
|
|
|
.rangeid = canvas_pic_rangeid,
|
|
|
|
},
|
2023-01-17 02:33:47 +00:00
|
|
|
[canvas_fitpic] = {
|
|
|
|
.size = sizeof (qpic_t *),
|
|
|
|
.name = "fitpic",
|
|
|
|
.rangeid = canvas_fitpic_rangeid,
|
|
|
|
},
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_subpic] = {
|
|
|
|
.size = sizeof (canvas_subpic_t),
|
|
|
|
.name = "subpic",
|
|
|
|
.rangeid = canvas_subpic_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_cachepic] = {
|
|
|
|
.size = sizeof (const char *),
|
|
|
|
.name = "cachepic",
|
|
|
|
.rangeid = canvas_cachepic_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_fill] = {
|
|
|
|
.size = sizeof (byte),
|
|
|
|
.name = "fill",
|
|
|
|
.rangeid = canvas_fill_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_charbuff] = {
|
|
|
|
.size = sizeof (draw_charbuffer_t *),
|
|
|
|
.name = "charbuffer",
|
|
|
|
.rangeid = canvas_charbuff_rangeid,
|
|
|
|
},
|
2023-07-01 10:49:49 +00:00
|
|
|
[canvas_passage_glyphs] = {
|
|
|
|
.size = sizeof (glyphset_t),
|
|
|
|
.name = "passage glyphs (copy)",
|
|
|
|
.rangeid = canvas_passage_glyphs_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_glyphs] = {
|
|
|
|
.size = sizeof (glyphset_t),
|
|
|
|
.name = "glyphs (copy)",
|
|
|
|
.rangeid = canvas_glyphs_rangeid,
|
|
|
|
},
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_func] = {
|
|
|
|
.size = sizeof (canvas_func_f),
|
|
|
|
.name = "func",
|
|
|
|
.rangeid = canvas_func_rangeid,
|
|
|
|
},
|
2023-01-21 18:43:58 +00:00
|
|
|
[canvas_lateupdate] = {
|
|
|
|
.size = sizeof (canvas_update_f),
|
|
|
|
.name = "lateupdate",
|
|
|
|
.rangeid = canvas_lateupdate_rangeid,
|
|
|
|
},
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_outline] = {
|
|
|
|
.size = sizeof (byte),
|
|
|
|
.name = "outline",
|
|
|
|
.rangeid = canvas_outline_rangeid,
|
|
|
|
},
|
|
|
|
[canvas_canvas] = {
|
|
|
|
.size = sizeof (canvas_t),
|
|
|
|
.name = "canvas",
|
|
|
|
.destroy = canvas_canvas_destroy,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef void (*canvas_sysfunc_f) (canvas_system_t *canvas_sys,
|
|
|
|
ecs_pool_t *pool, ecs_range_t range);
|
|
|
|
static void
|
|
|
|
draw_update (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type func = (canvas_update_f *) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
(*func++) (View_FromEntity (viewsys, *ent++));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_tile_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
view_pos_t len = View_GetLen (view);
|
|
|
|
r_funcs->Draw_TileClear (pos.x, pos.y, len.x, len.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_pic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type pic = (qpic_t **) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
r_funcs->Draw_Pic (pos.x, pos.y, *pic);
|
|
|
|
}
|
|
|
|
pic++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-17 02:33:47 +00:00
|
|
|
static void
|
|
|
|
draw_fitpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2023-01-17 02:33:47 +00:00
|
|
|
__auto_type pic = (qpic_t **) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
view_pos_t len = View_GetLen (view);
|
|
|
|
r_funcs->Draw_FitPic (pos.x, pos.y, len.x, len.y, *pic);
|
|
|
|
}
|
|
|
|
pic++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-20 10:45:48 +00:00
|
|
|
static void
|
|
|
|
draw_subpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type subpic = (canvas_subpic_t *) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
r_funcs->Draw_SubPic (pos.x, pos.y, subpic->pic,
|
|
|
|
subpic->x, subpic->y, subpic->w, subpic->h);
|
|
|
|
}
|
|
|
|
subpic++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_cachepic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type name = (const char **) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
qpic_t *pic = r_funcs->Draw_CachePic (*name, 1);
|
|
|
|
r_funcs->Draw_Pic (pos.x, pos.y, pic);
|
|
|
|
}
|
|
|
|
name++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_fill_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type fill = (byte *) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
view_pos_t len = View_GetLen (view);
|
|
|
|
r_funcs->Draw_Fill (pos.x, pos.y, len.x, len.y, *fill);
|
|
|
|
}
|
|
|
|
fill++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_charbuff_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type charbuff = (draw_charbuffer_t **) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
r_funcs->Draw_CharBuffer (pos.x, pos.y, *charbuff);
|
|
|
|
}
|
|
|
|
charbuff++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_func_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type func = (canvas_func_f *) pool->data + range.start;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t pos = View_GetAbs (view);
|
|
|
|
view_pos_t len = View_GetLen (view);
|
|
|
|
(*func) (pos, len);
|
|
|
|
}
|
|
|
|
func++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_outline_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
|
|
|
|
uint32_t count = range.end - range.start;
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t *ent = pool->dense + range.start;
|
2022-12-20 10:45:48 +00:00
|
|
|
__auto_type col = (byte *) pool->data + range.start;
|
|
|
|
__auto_type line = r_funcs->Draw_Line;
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = View_FromEntity (viewsys, *ent++);
|
|
|
|
byte c = *col++;
|
2023-01-21 02:20:09 +00:00
|
|
|
if (View_GetVisible (view)) {
|
2022-12-20 10:45:48 +00:00
|
|
|
view_pos_t p = View_GetAbs (view);
|
|
|
|
view_pos_t l = View_GetLen (view);
|
|
|
|
view_pos_t q = { p.x + l.x - 1, p.y + l.y - 1 };
|
|
|
|
line (p.x, p.y, q.x, p.y, c);
|
|
|
|
line (p.x, q.y, q.x, q.y, c);
|
|
|
|
line (p.x, p.y, p.x, q.y, c);
|
|
|
|
line (q.x, p.y, q.x, q.y, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-01 10:49:49 +00:00
|
|
|
static void
|
2023-07-04 08:17:16 +00:00
|
|
|
draw_glyph_refs (view_pos_t *abs, glyphset_t *glyphset, glyphref_t *gref,
|
|
|
|
uint32_t color)
|
2023-07-01 10:49:49 +00:00
|
|
|
{
|
|
|
|
uint32_t count = gref->count;
|
|
|
|
glyphobj_t *glyph = glyphset->glyphs + gref->start;
|
|
|
|
|
|
|
|
while (count-- > 0) {
|
|
|
|
glyphobj_t *g = glyph++;
|
|
|
|
r_funcs->Draw_Glyph (abs->x + g->x, abs->y + g->y,
|
2023-07-04 08:17:16 +00:00
|
|
|
g->fontid, g->glyphid, color);
|
2023-07-01 10:49:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_box (view_pos_t *abs, view_pos_t *len, uint32_t ind, int c)
|
|
|
|
{
|
|
|
|
int x = abs[ind].x;
|
|
|
|
int y = abs[ind].y;
|
|
|
|
int w = len[ind].x;
|
|
|
|
int h = len[ind].y;
|
|
|
|
r_funcs->Draw_Line (x, y, x + w, y, c);
|
|
|
|
r_funcs->Draw_Line (x, y + h, x + w, y + h, c);
|
|
|
|
r_funcs->Draw_Line (x, y, x, y + h, c);
|
|
|
|
r_funcs->Draw_Line (x + w, y, x + w, y + h, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_glyphs (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range)
|
|
|
|
{
|
|
|
|
auto reg = canvas_sys->reg;
|
|
|
|
uint32_t glyphs = canvas_sys->text_base + text_glyphs;
|
2023-07-04 08:17:16 +00:00
|
|
|
uint32_t color = canvas_sys->text_base + text_color;
|
2023-07-01 10:49:49 +00:00
|
|
|
uint32_t vhref = canvas_sys->view_base + view_href;
|
|
|
|
uint32_t count = range.end - range.start;
|
|
|
|
uint32_t *ent = pool->dense + range.start;
|
|
|
|
auto glyphset = (glyphset_t *) pool->data + range.start;
|
|
|
|
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t view = { .id = *ent++, .reg = reg, .comp = vhref};
|
|
|
|
glyphset_t *gs = glyphset++;
|
|
|
|
if (View_GetVisible (view)) {
|
|
|
|
view_pos_t abs = View_GetAbs (view);
|
|
|
|
glyphref_t *gref = Ent_GetComponent (view.id, glyphs, reg);
|
2023-07-04 08:17:16 +00:00
|
|
|
uint32_t *c = Ent_SafeGetComponent (view.id, color, reg);
|
|
|
|
draw_glyph_refs (&abs, gs, gref, c ? *c : 254);
|
2023-07-01 10:49:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_passage_glyphs (canvas_system_t *canvas_sys, ecs_pool_t *pool,
|
|
|
|
ecs_range_t range)
|
|
|
|
{
|
|
|
|
auto reg = canvas_sys->reg;
|
|
|
|
uint32_t glyphs = canvas_sys->text_base + text_glyphs;
|
2023-07-04 08:17:16 +00:00
|
|
|
uint32_t color = canvas_sys->text_base + text_color;
|
2023-07-01 10:49:49 +00:00
|
|
|
uint32_t vhref = canvas_sys->view_base + view_href;
|
|
|
|
uint32_t count = range.end - range.start;
|
|
|
|
uint32_t *ent = pool->dense + range.start;
|
|
|
|
auto glyphset = (glyphset_t *) pool->data + range.start;
|
|
|
|
|
|
|
|
while (count-- > 0) {
|
|
|
|
view_t psg_view = { .id = *ent++, .reg = reg, .comp = vhref};
|
|
|
|
// first child is always a paragraph view, and all views after the
|
|
|
|
// first paragraph's first child are all text views
|
|
|
|
view_t para_view = View_GetChild (psg_view, 0);
|
|
|
|
view_t text_view = View_GetChild (para_view, 0);
|
|
|
|
hierref_t *href = View_GetRef (text_view);
|
|
|
|
glyphset_t *gs = glyphset++;
|
|
|
|
hierarchy_t *h = href->hierarchy;
|
|
|
|
view_pos_t *abs = h->components[view_abs];
|
|
|
|
view_pos_t *len = h->components[view_len];
|
|
|
|
|
|
|
|
for (uint32_t i = href->index; i < h->num_objects; i++) {
|
|
|
|
glyphref_t *gref = Ent_GetComponent (h->ent[i], glyphs, reg);
|
2023-07-04 08:17:16 +00:00
|
|
|
uint32_t *c = Ent_SafeGetComponent (h->ent[i], color, reg);
|
|
|
|
draw_glyph_refs (&abs[i], gs, gref, c ? *c : 254);
|
2023-07-01 10:49:49 +00:00
|
|
|
|
|
|
|
if (0) draw_box (abs, len, i, 253);
|
|
|
|
}
|
|
|
|
if (0) {
|
|
|
|
for (uint32_t i = 1; i < href->index; i++) {
|
|
|
|
draw_box (abs, len, i, 251);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-20 10:45:48 +00:00
|
|
|
void
|
2022-12-20 16:54:10 +00:00
|
|
|
Canvas_Draw (canvas_system_t canvas_sys)
|
2022-12-20 10:45:48 +00:00
|
|
|
{
|
|
|
|
static canvas_sysfunc_f draw_func[canvas_comp_count] = {
|
|
|
|
[canvas_update] = draw_update,
|
2023-01-21 18:43:58 +00:00
|
|
|
[canvas_updateonce] = draw_update,
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_tile] = draw_tile_views,
|
|
|
|
[canvas_pic] = draw_pic_views,
|
2023-01-17 02:33:47 +00:00
|
|
|
[canvas_fitpic] = draw_fitpic_views,
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_subpic] = draw_subpic_views,
|
|
|
|
[canvas_cachepic] = draw_cachepic_views,
|
|
|
|
[canvas_fill] = draw_fill_views,
|
|
|
|
[canvas_charbuff] = draw_charbuff_views,
|
2023-07-01 10:49:49 +00:00
|
|
|
[canvas_passage_glyphs] = draw_passage_glyphs,
|
|
|
|
[canvas_glyphs] = draw_glyphs,
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_func] = draw_func_views,
|
2023-01-21 18:43:58 +00:00
|
|
|
[canvas_lateupdate] = draw_update,
|
2022-12-20 10:45:48 +00:00
|
|
|
[canvas_outline] = draw_outline_views,
|
|
|
|
};
|
|
|
|
|
2023-07-01 10:49:49 +00:00
|
|
|
auto reg = canvas_sys.reg;
|
2022-12-20 16:54:10 +00:00
|
|
|
uint32_t comp = canvas_sys.base + canvas_canvas;
|
2023-07-01 10:49:49 +00:00
|
|
|
ecs_pool_t *canvas_pool = ®->comp_pools[comp];
|
2023-01-16 02:32:12 +00:00
|
|
|
uint32_t count = canvas_pool->count;
|
|
|
|
//uint32_t *entities = canvas_pool->dense;
|
|
|
|
__auto_type canvases = (canvas_t *) canvas_pool->data;
|
2022-12-20 10:45:48 +00:00
|
|
|
|
|
|
|
while (count-- > 0) {
|
|
|
|
canvas_t *canvas = canvases++;
|
|
|
|
//uint32_t ent = *entities++;
|
|
|
|
|
2023-07-01 10:53:26 +00:00
|
|
|
if (!canvas->visible) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-12-20 10:45:48 +00:00
|
|
|
for (int i = 0; i < canvas_comp_count; i++) {
|
|
|
|
if (draw_func[i]) {
|
2023-07-01 10:49:49 +00:00
|
|
|
uint32_t c = canvas_sys.base + i;
|
|
|
|
uint32_t rid = canvas->range[i];
|
|
|
|
ecs_range_t range = ECS_GetSubpoolRange (reg, c, rid);
|
|
|
|
if (range.end - range.start) {
|
|
|
|
ecs_pool_t *pool = ®->comp_pools[c];
|
|
|
|
draw_func[i] (&canvas_sys, pool, range);
|
|
|
|
}
|
2022-12-20 10:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-20 18:26:02 +00:00
|
|
|
{
|
2023-07-01 10:49:49 +00:00
|
|
|
ecs_pool_t *pool = ®->comp_pools[canvas_updateonce];
|
|
|
|
ecs_subpool_t *subpool = ®->subpools[canvas_updateonce];
|
2023-01-20 18:26:02 +00:00
|
|
|
pool->count = 0;
|
|
|
|
uint32_t rcount = subpool->num_ranges - subpool->available;
|
|
|
|
memset (subpool->ranges, 0, rcount * sizeof (*subpool->ranges));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Canvas_InitSys (canvas_system_t *canvas_sys, ecs_registry_t *reg)
|
|
|
|
{
|
|
|
|
*canvas_sys = (canvas_system_t) {
|
|
|
|
.reg = reg,
|
|
|
|
.base = ECS_RegisterComponents (reg, canvas_components,
|
|
|
|
canvas_comp_count),
|
|
|
|
.view_base = ECS_RegisterComponents (reg, view_components,
|
|
|
|
view_comp_count),
|
|
|
|
.text_base = ECS_RegisterComponents (reg, text_components,
|
|
|
|
text_comp_count),
|
2023-07-04 15:40:29 +00:00
|
|
|
.imui_base = ECS_RegisterComponents (reg, imui_components,
|
|
|
|
imui_comp_count),
|
2023-01-20 18:26:02 +00:00
|
|
|
};
|
2022-12-20 10:45:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-12-20 16:54:10 +00:00
|
|
|
Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent)
|
2022-12-20 10:45:48 +00:00
|
|
|
{
|
2023-07-09 03:06:08 +00:00
|
|
|
canvas_t canvas = {
|
|
|
|
.reg = canvas_sys.reg,
|
|
|
|
.base = canvas_sys.base,
|
|
|
|
.visible = true
|
|
|
|
};
|
2023-07-09 13:14:02 +00:00
|
|
|
for (uint32_t i = 0; i < canvas_canvas; i++) {
|
2022-12-20 16:54:10 +00:00
|
|
|
canvas.range[i] = ECS_NewSubpoolRange (canvas_sys.reg,
|
|
|
|
canvas_sys.base + i);
|
2022-12-20 10:45:48 +00:00
|
|
|
}
|
2022-12-20 16:54:10 +00:00
|
|
|
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);
|
2022-12-20 10:45:48 +00:00
|
|
|
}
|
2023-01-16 02:32:12 +00:00
|
|
|
|
2023-01-20 06:57:29 +00:00
|
|
|
uint32_t
|
|
|
|
Canvas_New (canvas_system_t canvas_sys)
|
|
|
|
{
|
|
|
|
uint32_t ent = ECS_NewEntity (canvas_sys.reg);
|
|
|
|
Canvas_AddToEntity (canvas_sys, ent);
|
|
|
|
return ent;
|
|
|
|
}
|
|
|
|
|
2023-01-16 02:32:12 +00:00
|
|
|
static int
|
|
|
|
canvas_href_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;
|
|
|
|
ecs_registry_t *reg = canvas_sys->reg;
|
|
|
|
uint32_t href = canvas_sys->view_base + view_href;
|
|
|
|
hierref_t *ref_a = Ent_GetComponent (enta, href, reg);
|
|
|
|
hierref_t *ref_b = Ent_GetComponent (entb, href, reg);
|
|
|
|
if (ref_a->hierarchy == ref_b->hierarchy) {
|
|
|
|
return ref_a->index - ref_b->index;
|
|
|
|
}
|
|
|
|
ptrdiff_t diff = ref_a->hierarchy - ref_b->hierarchy;
|
|
|
|
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2023-01-20 18:26:02 +00:00
|
|
|
uint32_t rid = canvas->range[component];
|
|
|
|
uint32_t c = component + canvas_sys.base;
|
|
|
|
ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, c, rid);
|
|
|
|
ECS_SortComponentPoolRange (canvas_sys.reg, c, range,
|
2023-01-16 02:32:12 +00:00
|
|
|
canvas_href_cmp, &canvas_sys);
|
|
|
|
}
|
2023-01-20 18:26:02 +00:00
|
|
|
|
|
|
|
void
|
2023-07-08 11:56:40 +00:00
|
|
|
Canvas_SetLen (canvas_system_t canvas_sys, uint32_t ent, view_pos_t len)
|
2023-01-20 18:26:02 +00:00
|
|
|
{
|
2023-07-08 11:56:40 +00:00
|
|
|
view_t view = Canvas_GetRootView (canvas_sys, ent);
|
|
|
|
View_SetLen (view, len.x, len.y);
|
|
|
|
View_UpdateHierarchy (view);
|
2023-01-20 18:26:02 +00:00
|
|
|
}
|
2023-07-09 13:18:04 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
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 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;
|
|
|
|
if (!diff) {
|
|
|
|
diff = canvasa->draw_order - canvasb->draw_order;
|
|
|
|
}
|
|
|
|
if (!diff) {
|
|
|
|
// order possibly undefined, but at least stable so long as the entity
|
|
|
|
// ids are stable
|
|
|
|
diff = enta - entb;
|
|
|
|
}
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|