initial button test
This commit is contained in:
parent
6967f4106e
commit
c101379150
6 changed files with 204 additions and 11 deletions
30
examples/button.c
Normal file
30
examples/button.c
Normal 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)
|
||||||
|
);
|
||||||
|
}
|
|
@ -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__ })
|
||||||
|
|
||||||
|
|
|
@ -62,4 +62,4 @@ typedef union {
|
||||||
|
|
||||||
typedef PtkVec4 PtkColorA;
|
typedef PtkVec4 PtkColorA;
|
||||||
|
|
||||||
#endif // _PTK_PTK_VEC_H
|
#endif // PTK_PTK_VEC_H_
|
||||||
|
|
39
src/ptk.c
39
src/ptk.c
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue