initial button test

This commit is contained in:
jacekpoz 2024-08-09 17:16:35 +02:00
parent 6967f4106e
commit c101379150
Signed by: poz
SSH key fingerprint: SHA256:JyLeVWE4bF3tDnFeUpUaJsPsNlJyBldDGV/dIKSLyN8
6 changed files with 204 additions and 11 deletions

30
examples/button.c Normal file
View file

@ -0,0 +1,30 @@
#include <stdlib.h>
#include <ptk.h>
#include <ptk_log.h>
static PtkRect *r;
static void on_press(int button, int action, int mods) {
(void)button; (void)action; (void)mods;
PTK_DEBUG("pressed!");
r->color.r = r->color.r + (1.0f / 255.0f);
if (r->color.r == 256.0f) {
r->color.r = 0.0f;
}
}
int main(void) {
if (!ptk_init(800, 600, "button", (PtkVersion){ .major = 0, .minor = 1, .patch = 0 })) {
return EXIT_FAILURE;
}
r = (PtkRect *)ptk_rect(
(PtkPos){ .x = 100.0f, .y = 100.0f },
(PtkSize){ .w = 100.0f, .h = 50.0f },
(PtkColor){ .r = 1.0f, .g = 0.0f, .b = 0.0f }
);
return ptk_run(
ptk_button((PtkHandle)r, on_press)
);
}

View file

@ -23,6 +23,7 @@ typedef enum {
PTK_COMPONENT_TYPE_TRIANGLE = 1, PTK_COMPONENT_TYPE_TRIANGLE = 1,
PTK_COMPONENT_TYPE_RECT = 2, PTK_COMPONENT_TYPE_RECT = 2,
PTK_COMPONENT_TYPE_ELLIPSE = 3, PTK_COMPONENT_TYPE_ELLIPSE = 3,
PTK_COMPONENT_TYPE_BUTTON = 4,
} PtkComponentType; } PtkComponentType;
typedef struct PtkComponent { typedef struct PtkComponent {
@ -55,12 +56,21 @@ typedef struct PtkEllipse {
PtkColor color; PtkColor color;
} PtkEllipse; } PtkEllipse;
typedef void (*MouseButtonCallback)(int button, int action, int mods);
typedef struct PtkButton {
PtkComponentType type;
PtkHandle hitbox;
MouseButtonCallback on_press;
} PtkButton;
PtkHandle ptk_box(size_t child_count, PtkHandle *children); PtkHandle ptk_box(size_t child_count, PtkHandle *children);
PtkHandle ptk_triangle(PtkPos vertices[3], PtkColor color); PtkHandle ptk_triangle(PtkPos vertices[3], PtkColor color);
PtkHandle ptk_rect(PtkPos top_left, PtkSize size, PtkColor color); PtkHandle ptk_rect(PtkPos top_left, PtkSize size, PtkColor color);
PtkHandle ptk_square(PtkPos top_left, float size, PtkColor color); PtkHandle ptk_square(PtkPos top_left, float size, PtkColor color);
PtkHandle ptk_ellipse(PtkPos center, PtkSize radii, PtkColor color); PtkHandle ptk_ellipse(PtkPos center, PtkSize radii, PtkColor color);
PtkHandle ptk_circle(PtkPos center, float radius, PtkColor color); PtkHandle ptk_circle(PtkPos center, float radius, PtkColor color);
PtkHandle ptk_button(PtkHandle hitbox, MouseButtonCallback on_press);
#define PTK_BOX(...) ptk_box(sizeof((PtkHandle []){ __VA_ARGS__ }) / sizeof(PtkHandle), (PtkHandle []) { __VA_ARGS__ }) #define PTK_BOX(...) ptk_box(sizeof((PtkHandle []){ __VA_ARGS__ }) / sizeof(PtkHandle), (PtkHandle []) { __VA_ARGS__ })

View file

@ -62,4 +62,4 @@ typedef union {
typedef PtkVec4 PtkColorA; typedef PtkVec4 PtkColorA;
#endif // _PTK_PTK_VEC_H #endif // PTK_PTK_VEC_H_

View file

@ -21,11 +21,27 @@
static GLFWwindow *g_window = NULL; static GLFWwindow *g_window = NULL;
void framebuffer_resize_callback(GLFWwindow *window, int width, int height) { static void framebuffer_resize_callback(GLFWwindow *window, int width, int height) {
(void)window; (void)width; (void)height; (void)window; (void)width; (void)height;
g_framebuffer_resized = true; g_framebuffer_resized = true;
} }
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
(void)window; (void)scancode; (void)action; (void)mods;
if (key == GLFW_KEY_SPACE) {
for (size_t i = 0; i < g_vertices.size; ++i) {
g_vertices.data[i].pos.x += 1.0f;
}
vk_transfer_vertex_data();
}
}
static void mouse_button_callback(GLFWwindow *window, int button, int action, int mods) {
double x, y;
glfwGetCursorPos(window, &x, &y);
vk_handle_mouse_button_input((PtkPos){ .x = x, .y = y }, button, action, mods);
}
PTK_OPTION_DEFINE(PtkLogLevel); PTK_OPTION_DEFINE(PtkLogLevel);
PTK_OPTION(PtkLogLevel) get_log_level(void) { PTK_OPTION(PtkLogLevel) get_log_level(void) {
@ -101,6 +117,8 @@ bool ptk_init(size_t width, size_t height, const char *title, PtkVersion applica
} }
glfwSetFramebufferSizeCallback(g_window, framebuffer_resize_callback); glfwSetFramebufferSizeCallback(g_window, framebuffer_resize_callback);
glfwSetKeyCallback(g_window, key_callback);
glfwSetMouseButtonCallback(g_window, mouse_button_callback);
vk_components_init(); vk_components_init();
@ -158,8 +176,20 @@ PtkHandle ptk_circle(PtkPos center, float radius, PtkColor color) {
return ptk_ellipse(center, (PtkSize){ .w = radius, .h = radius }, color); return ptk_ellipse(center, (PtkSize){ .w = radius, .h = radius }, color);
} }
PtkHandle ptk_button(PtkHandle hitbox, MouseButtonCallback on_press) {
PtkButton *ret = malloc(sizeof(PtkButton));
ret->type = PTK_COMPONENT_TYPE_BUTTON;
ret->hitbox = hitbox;
ret->on_press = on_press;
return (PtkHandle)ret;
}
void init_components(PtkHandle root) { void init_components(PtkHandle root) {
switch (root->type) { switch (root->type) {
case PTK_COMPONENT_TYPE_BOX: {
vk_box((PtkBox *)root);
} break;
case PTK_COMPONENT_TYPE_TRIANGLE: { case PTK_COMPONENT_TYPE_TRIANGLE: {
vk_triangle((PtkTriangle *)root); vk_triangle((PtkTriangle *)root);
} break; } break;
@ -169,11 +199,8 @@ void init_components(PtkHandle root) {
case PTK_COMPONENT_TYPE_ELLIPSE: { case PTK_COMPONENT_TYPE_ELLIPSE: {
vk_ellipse((PtkEllipse *)root); vk_ellipse((PtkEllipse *)root);
} break; } break;
case PTK_COMPONENT_TYPE_BOX: { case PTK_COMPONENT_TYPE_BUTTON: {
PtkBox *box = (PtkBox *)root; vk_button((PtkButton *)root);
for (size_t i = 0; i < box->child_count; ++i) {
init_components(box->children[i]);
}
} break; } break;
} }
} }

View file

@ -1,4 +1,5 @@
#include <ptk.h> #include <ptk.h>
#include <ptk_log.h>
#include <ptk_vk/components.h> #include <ptk_vk/components.h>
#include <ptk_vk/init.h> #include <ptk_vk/init.h>
@ -72,9 +73,7 @@ void vk_rect(PtkRect *rect) {
_vk_rect(rect, PTK_COMPONENT_TYPE_RECT); _vk_rect(rect, PTK_COMPONENT_TYPE_RECT);
} }
void vk_ellipse(PtkEllipse *ellipse) { void _vk_ellipse(PtkEllipse *ellipse, PtkComponentType type) {
PTK_LIST_ADD(PtkHandle, m_components, ellipse);
PtkPos top_left = { PtkPos top_left = {
.x = ellipse->center.x - ellipse->radii.w, .x = ellipse->center.x - ellipse->radii.w,
.y = ellipse->center.y - ellipse->radii.h, .y = ellipse->center.y - ellipse->radii.h,
@ -85,7 +84,130 @@ void vk_ellipse(PtkEllipse *ellipse) {
.h = ellipse->radii.h * 2.0f, .h = ellipse->radii.h * 2.0f,
}; };
_vk_rect((PtkRect *)ptk_rect(top_left, size, ellipse->color), PTK_COMPONENT_TYPE_ELLIPSE); _vk_rect((PtkRect *)ptk_rect(top_left, size, ellipse->color), type);
}
void vk_ellipse(PtkEllipse *ellipse) {
PTK_LIST_ADD(PtkHandle, m_components, ellipse);
_vk_ellipse(ellipse, PTK_COMPONENT_TYPE_ELLIPSE);
}
void _vk_box(PtkBox *box, PtkComponentType type) {
for (size_t i = 0; i < box->child_count; ++i) {
PtkHandle child = box->children[i];
switch (child->type) {
case PTK_COMPONENT_TYPE_BOX: {
_vk_box((PtkBox *)child, type);
} break;
case PTK_COMPONENT_TYPE_TRIANGLE: {
_vk_triangle((PtkTriangle *)child, type, 0);
} break;
case PTK_COMPONENT_TYPE_RECT: {
_vk_rect((PtkRect *)child, type);
} break;
case PTK_COMPONENT_TYPE_ELLIPSE: {
_vk_ellipse((PtkEllipse *)child, type);
} break;
default:
return;
}
}
}
void vk_box(PtkBox *box) {
PTK_LIST_ADD(PtkHandle, m_components, box);
_vk_box(box, PTK_COMPONENT_TYPE_BOX);
}
void vk_button(PtkButton *button) {
PTK_LIST_ADD(PtkHandle, m_components, button);
switch (button->hitbox->type) {
case PTK_COMPONENT_TYPE_BOX: {
_vk_box((PtkBox *)button->hitbox, PTK_COMPONENT_TYPE_BUTTON);
} break;
case PTK_COMPONENT_TYPE_TRIANGLE: {
_vk_triangle((PtkTriangle *)button->hitbox, PTK_COMPONENT_TYPE_BUTTON, 0);
} break;
case PTK_COMPONENT_TYPE_RECT: {
_vk_rect((PtkRect *)button->hitbox, PTK_COMPONENT_TYPE_BUTTON);
} break;
case PTK_COMPONENT_TYPE_ELLIPSE: {
_vk_ellipse((PtkEllipse *)button->hitbox, PTK_COMPONENT_TYPE_BUTTON);
} break;
default:
return;
}
}
bool triangle_intersects(PtkTriangle t, PtkPos p) {
PtkPos p0 = t.vertices[0];
PtkPos p1 = t.vertices[1];
PtkPos p2 = t.vertices[2];
float a = 1.0f/2.0f * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
int sign = a < 0.0f ? -1 : 1;
float s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
float r = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
return s > 0 && r > 0 && (s + r) < 2 * a * sign;
}
bool rect_intersects(PtkRect r, PtkPos p) {
bool intersects_x = r.top_left.x <= p.x
&& r.top_left.x + r.top_left.w >= p.x;
bool intersects_y = r.top_left.y <= p.y
&& r.top_left.y + r.top_left.h >= p.y;
return intersects_x && intersects_y;
}
bool ellipse_intersects(PtkEllipse e, PtkPos p) {
float x = p.x - e.center.x;
float rx = e.radii.x;
float y = p.y - e.center.y;
float ry = e.radii.y;
return ((x * x) / (rx * rx)) + ((y * y) / (ry * ry)) <= 1.0f;
}
bool intersects(PtkHandle component, PtkPos point) {
switch (component->type) {
case PTK_COMPONENT_TYPE_BOX: {
PtkBox *box = (PtkBox *)component;
for (size_t i = 0; i < box->child_count; ++i) {
if (intersects(box->children[i], point)) {
return true;
}
}
return false;
}
case PTK_COMPONENT_TYPE_TRIANGLE:
return triangle_intersects(*(PtkTriangle *)component, point);
case PTK_COMPONENT_TYPE_RECT:
return rect_intersects(*(PtkRect *)component, point);
case PTK_COMPONENT_TYPE_ELLIPSE:
return ellipse_intersects(*(PtkEllipse *)component, point);
case PTK_COMPONENT_TYPE_BUTTON:
return intersects(((PtkButton *)component)->hitbox, point);
}
}
void vk_handle_mouse_button_input(PtkPos cursor_pos, int button, int action, int mods) {
for (size_t i = 0; i < m_components.size; ++i) {
PtkHandle current = m_components.data[i];
if (current->type != PTK_COMPONENT_TYPE_BUTTON) {
continue;
}
PtkButton *b = (PtkButton *)current;
if (intersects((PtkHandle)b, cursor_pos)) {
b->on_press(button, action, mods);
}
}
} }
void vk_components_cleanup(void) { void vk_components_cleanup(void) {

View file

@ -17,9 +17,13 @@ extern PTK_LIST(Vertex) g_vertices;
void vk_components_init(void); void vk_components_init(void);
void vk_box(PtkBox *box);
void vk_triangle(PtkTriangle *triangle); void vk_triangle(PtkTriangle *triangle);
void vk_rect(PtkRect *rect); void vk_rect(PtkRect *rect);
void vk_ellipse(PtkEllipse *ellipse); void vk_ellipse(PtkEllipse *ellipse);
void vk_button(PtkButton *button);
void vk_handle_mouse_button_input(PtkPos cursor_pos, int button, int action, int mode);
void vk_components_cleanup(void); void vk_components_cleanup(void);