From 1037eaaeffc8a96340cc87d0d995c35962ae4002 Mon Sep 17 00:00:00 2001 From: jacekpoz Date: Mon, 9 Sep 2024 23:52:15 +0200 Subject: [PATCH] Squashed commit of the following: commit 51a16fcec320ac34fdc7d89d78f74c56e9f5094f Author: jacekpoz Date: Mon Sep 9 23:07:46 2024 +0200 mark all components to be updated during initialization commit 7952918cdb96f9c4658eb083dde3c4182c619c2f Author: jacekpoz Date: Mon Sep 9 23:07:31 2024 +0200 clear caches before updating component commit 40c2329b3c8591d275f725333682575131ea8224 Author: jacekpoz Date: Mon Sep 9 22:25:22 2024 +0200 implement vertex and index caches hopefully these work and actually help with performance commit be1ae4c531f22f18c1923252afce08791f592f91 Author: jacekpoz Date: Mon Sep 9 21:11:52 2024 +0200 initial tree impl without any updating logic --- include/ptk.h | 3 + src/ptk.c | 25 ++++++++ src/ptk_list.h | 8 +++ src/ptk_vk/components.c | 139 +++++++++++++++++++++++++++++++--------- 4 files changed, 146 insertions(+), 29 deletions(-) diff --git a/include/ptk.h b/include/ptk.h index c114fdf..d6e6e06 100644 --- a/include/ptk.h +++ b/include/ptk.h @@ -28,10 +28,13 @@ typedef enum { PTK_COMPONENT_TYPE_CLICKABLE = 4, } PtkComponentType; +const char *ptk_component_type_to_str(PtkComponentType type); + PTK_LIST_DEFINE(PtkHandle); #define PTK_COMPONENT_DEFINE(name, ...) \ typedef struct name {\ + uint64_t id;\ PtkComponentType type;\ PtkHandle parent;\ PTK_LIST(PtkHandle) children;\ diff --git a/src/ptk.c b/src/ptk.c index b4ea02c..1eabce2 100644 --- a/src/ptk.c +++ b/src/ptk.c @@ -142,13 +142,30 @@ bool ptk_init(const size_t width, const size_t height, const char *title, const return true; } +const char *ptk_component_type_to_str(PtkComponentType type) { + const char *res; + switch (type) { + case PTK_COMPONENT_TYPE_BOX: res = "box"; break; + case PTK_COMPONENT_TYPE_TRIANGLE: res = "triangle"; break; + case PTK_COMPONENT_TYPE_RECT: res = "rect"; break; + case PTK_COMPONENT_TYPE_ELLIPSE: res = "ellipse"; break; + case PTK_COMPONENT_TYPE_CLICKABLE: res = "clickable"; break; + default: res = "unknown"; break; + } + return res; +} + +static uint64_t m_component_count = 0; + PtkHandle ptk_box(const size_t child_count, PtkHandle *children) { PtkComponent *ret = malloc(sizeof(PtkComponent)); *ret = (PtkComponent){ + .id = m_component_count, .type = PTK_COMPONENT_TYPE_BOX, .children = PTK_LIST_NEW(PtkHandle, child_count), }; PTK_LIST_ADD_ALL_P(PtkHandle, ret->children, children, child_count); + m_component_count += 1; return (PtkHandle)ret; } @@ -156,10 +173,12 @@ PtkHandle ptk_box(const size_t child_count, PtkHandle *children) { PtkHandle ptk_triangle(const PtkPos vertices[3], const PtkRGB color) { PtkTriangle *ret = malloc(sizeof(PtkTriangle)); *ret = (PtkTriangle){ + .id = m_component_count, .type = PTK_COMPONENT_TYPE_TRIANGLE, .color = color, }; memcpy(ret->vertices, vertices, sizeof(PtkPos) * 3); + m_component_count += 1; return (PtkHandle)ret; } @@ -167,11 +186,13 @@ PtkHandle ptk_triangle(const PtkPos vertices[3], const PtkRGB color) { PtkHandle ptk_rect(const PtkPos top_left, const PtkSize size, const PtkRGB color) { PtkRect *ret = malloc(sizeof(PtkRect)); *ret = (PtkRect){ + .id = m_component_count, .type = PTK_COMPONENT_TYPE_RECT, .top_left = top_left, .size = size, .color = color, }; + m_component_count += 1; return (PtkHandle)ret; } @@ -183,11 +204,13 @@ PtkHandle ptk_square(const PtkPos top_left, const float size, const PtkRGB color PtkHandle ptk_ellipse(const PtkPos center, const PtkSize radii, const PtkRGB color) { PtkEllipse *ret = malloc(sizeof(PtkEllipse)); *ret = (PtkEllipse){ + .id = m_component_count, .type = PTK_COMPONENT_TYPE_ELLIPSE, .center = center, .radii = radii, .color = color, }; + m_component_count += 1; return (PtkHandle)ret; } @@ -199,11 +222,13 @@ PtkHandle ptk_circle(const PtkPos center, const float radius, const PtkRGB color PtkHandle ptk_clickable(PtkHandle hitbox, const MouseButtonCallback on_press) { PtkClickable *ret = malloc(sizeof(PtkClickable)); *ret = (PtkClickable){ + .id = m_component_count, .type = PTK_COMPONENT_TYPE_CLICKABLE, .children = PTK_LIST_NEW(PtkHandle, 1), .on_press = on_press, }; PTK_LIST_ADD(PtkHandle, ret->children, hitbox); + m_component_count += 1; return (PtkHandle)ret; } diff --git a/src/ptk_list.h b/src/ptk_list.h index 911ec0d..d173c2f 100644 --- a/src/ptk_list.h +++ b/src/ptk_list.h @@ -23,6 +23,14 @@ #define PTK_LIST_REMOVE_AT(T, list, index) _remove_at_PtkList((void *)list.data, &list.size, index, sizeof(T)) +#define PTK_LIST_SET(T, list, index, elem) do {\ + while (list.allocated <= index) {\ + /* let's hope this doesn't fail !!! */\ + _grow_PtkList((void *)&list.data, &list.allocated, sizeof(T));\ + }\ + list.data[index] = elem;\ +} while (0) + bool _grow_PtkList(void **data, uint32_t *allocated, size_t element_size); bool _add_PtkList(void **data, uint32_t *size, uint32_t *allocated, void *elements, size_t element_count, size_t element_size); bool _remove_PtkList(void *data, uint32_t *size, void *elements, size_t element_count, size_t element_size); diff --git a/src/ptk_vk/components.c b/src/ptk_vk/components.c index ffa95fa..e2bd914 100644 --- a/src/ptk_vk/components.c +++ b/src/ptk_vk/components.c @@ -7,8 +7,25 @@ #include +PTK_LIST_DEFINE(bool); + static PtkHandle m_root_component; -static PTK_LIST(PtkHandle) m_components; +// TODO: figure out a way to actually use bool here +// this happens because PTK_LIST_DEFINE and PTK_LIST_NEW +// use PTK_LIST themselves, bool gets put through the first +// and turned into _Bool which is then used as the actual +// type's name; using PTK_LIST directly only processes it once +// so we have to use _Bool here +static PTK_LIST(_Bool) m_update; + +typedef PTK_LIST(Vertex) Vertices; +typedef PTK_LIST(uint32_t) Indices; + +PTK_LIST_DEFINE(Vertices); +PTK_LIST_DEFINE(Indices); + +PTK_LIST(Vertices) m_vertices_cache; +PTK_LIST(Indices) m_indices_cache; PTK_LIST(Vertex) g_vertices; PTK_LIST(uint32_t) g_indices; @@ -21,13 +38,19 @@ static const PtkVec2 uvs[] = { }; void vk_init_vertices(void) { - m_components = PTK_LIST_NEW(PtkHandle, 1); + m_update = PTK_LIST_NEW(bool, 1); + + m_vertices_cache = PTK_LIST_NEW(Vertices, 1); + m_indices_cache = PTK_LIST_NEW(Indices, 1); g_vertices = PTK_LIST_NEW(Vertex, 0); g_indices = PTK_LIST_NEW(uint32_t, 0); } void triangle(const PtkTriangle *triangle) { + PTK_LIST_SET(Vertices, m_vertices_cache, triangle->id, PTK_LIST_NEW(Vertex, 3)); + PTK_LIST_SET(Indices, m_indices_cache, triangle->id, PTK_LIST_NEW(uint32_t, 3)); + for (size_t i = 0; i < 3; ++i) { Vertex v = { .pos = triangle->vertices[i], @@ -39,10 +62,16 @@ void triangle(const PtkTriangle *triangle) { uint32_t old_vertex_count = g_vertices.size; PTK_LIST_ADD(Vertex, g_vertices, v); PTK_LIST_ADD(uint32_t, g_indices, old_vertex_count); + + PTK_LIST_ADD(Vertex, m_vertices_cache.data[triangle->id], v); + PTK_LIST_ADD(uint32_t, m_indices_cache.data[triangle->id], old_vertex_count); } } void rect(const PtkRect *rect) { + PTK_LIST_SET(Vertices, m_vertices_cache, rect->id, PTK_LIST_NEW(Vertex, 4)); + PTK_LIST_SET(Indices, m_indices_cache, rect->id, PTK_LIST_NEW(uint32_t, 6)); + const float x = rect->top_left.x; const float y = rect->top_left.y; const float w = rect->size.w; @@ -97,6 +126,19 @@ void rect(const PtkRect *rect) { PTK_LIST_ADD(uint32_t, g_indices, top_right_index); PTK_LIST_ADD(uint32_t, g_indices, bottom_left_index); PTK_LIST_ADD(uint32_t, g_indices, bottom_right_index); + + PTK_LIST_ADD(Vertex, m_vertices_cache.data[rect->id], top_right); + PTK_LIST_ADD(Vertex, m_vertices_cache.data[rect->id], bottom_left); + PTK_LIST_ADD(Vertex, m_vertices_cache.data[rect->id], top_left); + PTK_LIST_ADD(Vertex, m_vertices_cache.data[rect->id], bottom_right); + + PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], top_left_index); + PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], top_right_index); + PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], bottom_left_index); + + PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], top_right_index); + PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], bottom_left_index); + PTK_LIST_ADD(uint32_t, m_indices_cache.data[rect->id], bottom_right_index); } void ellipse(const PtkEllipse *ellipse) { @@ -117,19 +159,28 @@ void ellipse(const PtkEllipse *ellipse) { } void component(PtkHandle c) { - PTK_LIST_ADD(PtkHandle, m_components, c); + if (!m_update.data[c->id]) { + Vertices vcache = m_vertices_cache.data[c->id]; + Indices icache = m_indices_cache.data[c->id]; + PTK_LIST_ADD_ALL_P(Vertex, g_vertices, vcache.data, vcache.size); + PTK_LIST_ADD_ALL_P(uint32_t, g_indices, icache.data, icache.size); + } else { + PTK_LIST_SET(bool, m_update, c->id, false); + PTK_LIST_CLEAR(m_vertices_cache.data[c->id]); + PTK_LIST_CLEAR(m_indices_cache.data[c->id]); - switch (c->type) { - case PTK_COMPONENT_TYPE_TRIANGLE: { - triangle((PtkTriangle *)c); - } break; - case PTK_COMPONENT_TYPE_RECT: { - rect((PtkRect *)c); - } break; - case PTK_COMPONENT_TYPE_ELLIPSE: { - ellipse((PtkEllipse *)c); - } break; - default: break; + switch (c->type) { + case PTK_COMPONENT_TYPE_TRIANGLE: { + triangle((PtkTriangle *)c); + } break; + case PTK_COMPONENT_TYPE_RECT: { + rect((PtkRect *)c); + } break; + case PTK_COMPONENT_TYPE_ELLIPSE: { + ellipse((PtkEllipse *)c); + } break; + default: break; + } } PTK_LIST_FOR_EACH(PtkHandle, c->children, child, { child->parent = c; @@ -137,13 +188,20 @@ void component(PtkHandle c) { }) } +void init_component(PtkHandle c) { + PTK_LIST_SET(bool, m_update, c->id, true); + PTK_LIST_FOR_EACH(PtkHandle, c->children, child, { + init_component(child); + }) +} + void vk_init_components(PtkHandle root) { m_root_component = root; + init_component(root); vk_update_components(); } void vk_update_components(void) { - PTK_LIST_CLEAR(m_components); PTK_LIST_CLEAR(g_vertices); PTK_LIST_CLEAR(g_indices); component(m_root_component); @@ -202,31 +260,54 @@ bool intersects(const PtkHandle component, const PtkPos point) { } } +void set_component_updated(PtkHandle c) { + PTK_LIST_SET(bool, m_update, c->id, true); + if (c->parent != PTK_NULL_HANDLE) { + set_component_updated(c->parent); + } +} + +void handle_mouse(PtkHandle c, const PtkPos cursor_pos, const int button, const int mods) { + if (c->type != PTK_COMPONENT_TYPE_CLICKABLE) { + PTK_LIST_FOR_EACH(PtkHandle, c->children, child, { + handle_mouse(child, cursor_pos, button, mods); + }) + return; + } + + PtkClickable *clickable = (PtkClickable *)c; + + if (intersects((PtkHandle)clickable, cursor_pos)) { + clickable->on_press(clickable, button, mods); + // TODO: make some proper updating system + // currently if I just updated clickable it would mark + // its parents up to the root for an update + // but not its child - the actual hitbox; this is very ugly + // and should probably done in another way + set_component_updated(clickable->children.data[0]); + vk_update_components(); + } +} + void vk_handle_mouse_button_input(const PtkPos cursor_pos, const int button, const int action, const int mods) { if (action == GLFW_RELEASE) { return; } - PTK_LIST_FOR_EACH(PtkHandle, m_components, current, { - if (current->type != PTK_COMPONENT_TYPE_CLICKABLE) { - continue; - } + handle_mouse(m_root_component, cursor_pos, button, mods); +} - PtkClickable *c = (PtkClickable *)current; - - if (intersects((PtkHandle)c, cursor_pos)) { - c->on_press(c, button, mods); - vk_update_components(); - } +void cleanup_component(PtkHandle c) { + PTK_LIST_FOR_EACH(PtkHandle, c->children, child, { + cleanup_component(child); }) + + free(c); } void vk_components_cleanup(void) { - PTK_LIST_FOR_EACH(PtkHandle, m_components, c, { - free(c); - }) + cleanup_component(m_root_component); - PTK_LIST_FREE(m_components); PTK_LIST_FREE(g_vertices); PTK_LIST_FREE(g_indices); }