Compare commits

..

16 Commits

Author SHA1 Message Date
f419378183 Update node struct to know about noodle connected to it 2024-02-28 23:52:04 +00:00
46a4802ce6 Double buffer the nodes to avoid drawing lag 2024-02-28 22:33:28 +00:00
4ed86611b5 Fix what happens when a noodle gets released 2024-02-27 23:12:59 +00:00
Abdelrahman Said
b447e9d5a1 Update .gitignore 2024-02-26 07:25:25 +00:00
Abdelrahman Said
65d69bd570 Update build script 2024-02-26 07:24:49 +00:00
9570f31dc7 Remove unused include 2024-02-25 23:23:16 +00:00
547764764c Switch to using if statements instead of switch in event handling code 2024-02-25 22:42:07 +00:00
29bcfabda9 Move the node drawing code to a function 2024-02-25 21:21:04 +00:00
f03dad33a2 Move noodle correctly when the node it's connected to moves 2024-02-25 21:11:01 +00:00
8078a72deb Add support for maintaining connected noodle when parent node moves 2024-02-25 21:04:10 +00:00
f2faa56e5f Handle ui_noodle return states and start introducing connected nodes 2024-02-25 20:52:44 +00:00
a68d6997a5 Add different return states for ui_noodle 2024-02-25 20:52:25 +00:00
373e48216d Reorder ui functions 2024-02-25 20:33:04 +00:00
7b7a913c46 Simplify the immediate mode functions and move node
connection logic to the application level
2024-02-25 20:31:11 +00:00
bc6bb1afdc Update the node struct 2024-02-25 20:31:01 +00:00
b847f87ee5 Move line_from_origin and aabb functions to the window code 2024-02-25 20:30:26 +00:00
8 changed files with 302 additions and 202 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.cache
compile_commands.json
main
*.dSYM

View File

@@ -8,7 +8,7 @@ INCLUDE="\
-Iintern/wizapp/aliases \
-Iintern/wizapp/cpath/include \
-Iintern/wizapp/dstr/include \
$(find intern/wizapp/mem/include/ -type d | xargs -I{} printf "-I{} ") \
$(find intern/wizapp/mem/include -type d | xargs -I{} echo -n "-I{} ") \
"
SRC="\
intern/wizapp/cpath/src/*.c \

View File

@@ -7,11 +7,15 @@
#define MAX_NODES 1024
#define IO_INPUT_COUNT 0
#define OP_INPUT_COUNT 2
#define EMPTY_NODE 0
#define NODE_START 1
#define CONNECTION_START 1
typedef i32 (*node_func)(i32 a, i32 b);
typedef enum node_type node_type;
typedef union node_data node_data;
typedef struct node node;
typedef struct noodle noodle;
enum node_type {
NODE_TYPE_IO,
@@ -25,12 +29,21 @@ union node_data {
node_func func;
};
struct noodle {
line ln;
u64 connected_node;
u64 connection_idx;
};
struct node {
ui_node_elem node;
rect rec;
ui_elem_colours colours;
node_type type;
node_data data;
u64 inputs;
u64 connected;
noodle *noodles;
noodle **connected_noodles;
};
#endif // !NODES_H

View File

@@ -7,8 +7,6 @@
#include <stdbool.h>
#define MAX_UI_ELEMENTS 8192
#define RESERVED_UI_SLOT 0
#define UI_ELEM_START_INDEX 1
#define BUTTON_WIDTH 100
#define BUTTON_HEIGHT 40
@@ -16,9 +14,13 @@
#define NODE_WIDTH 70
#define NODE_HEIGHT 20
#define DEFAULT_NOODLE_LENGTH 60
typedef enum ui_elem_type ui_elem_type;
typedef struct ui_elem ui_elem;
typedef struct ui_ctx ui_ctx;
typedef struct ui_elem_colours ui_elem_colours;
typedef enum noodle_action noodle_action;
enum ui_elem_type {
UI_ELEM_NODE,
@@ -37,23 +39,15 @@ struct ui_elem {
ui_elem_type type;
};
typedef struct ui_elem_colours ui_elem_colours;
struct ui_elem_colours {
colour fill;
colour border;
};
typedef struct ui_noodle_elem ui_noodle_elem;
struct ui_noodle_elem {
line noodle;
u64 connected_node;
};
typedef struct ui_node_elem ui_node_elem;
struct ui_node_elem {
rect rec;
ui_noodle_elem *noodles;
u64 inputs;
enum noodle_action {
NOODLE_ACTION_NONE,
NOODLE_ACTION_DRAGGING,
NOODLE_ACTION_RELEASED,
};
struct ui_ctx {
@@ -75,7 +69,9 @@ void reset_ui_ctx(ui_ctx *ctx);
void handle_ui_events(const window *wnd, ui_ctx *ctx, const SDL_Event *event);
bool ui_button(const window *wnd, ui_ctx *ctx, rect rect,
ui_elem_colours colours);
ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
ui_elem_colours colours);
bool ui_node(const window *wnd, ui_ctx *ctx, rect rect,
ui_elem_colours colours);
noodle_action ui_noodle(const window *wnd, ui_ctx *ctx, line ln,
ui_elem_colours colours, rect parent_node);
#endif // !UI_H

View File

@@ -80,5 +80,7 @@ void draw_rect(const window *wnd, rect rec, colour colour);
void fill_triangle(const window *wnd, triangle triangle, colour colour);
void fill_quad(const window *wnd, quad qd, colour colour);
void fill_rect(const window *wnd, rect rec, colour colour);
line line_from_origin(point origin, f64 angle, i32 line_length);
bool aabb(rect rec, i32 x, i32 y);
#endif // !WINDOW_H

View File

@@ -25,15 +25,16 @@ struct compositor {
u32 active_window;
SDL_Event event;
bool running;
i64 node_hovered;
u64 count;
node *nodes;
bool move_node;
node *back_nodes;
ui_ctx ctx;
};
void add_node(compositor *comp, node_type type, node_data data, u64 inputs,
i32 x, i32 y, ui_elem_colours colours);
internal void add_node(compositor *comp, node_type type, node_data data,
u64 inputs, i32 x, i32 y, ui_elem_colours colours);
internal void update_node_graph(compositor *comp, const window *wnd);
internal void draw_node_graph(compositor *comp, const window *wnd);
i32 run_main_loop(void) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
@@ -46,6 +47,8 @@ i32 run_main_loop(void) {
mem_arena_init(&comp.arena, ARENA_CAPACITY);
comp.nodes = (node *)mem_arena_alloc(comp.arena, sizeof(node) * MAX_NODES);
comp.back_nodes =
(node *)mem_arena_alloc(comp.arena, sizeof(node) * MAX_NODES);
window *main_window = &(comp.windows[0]);
window *toolbox = &(comp.windows[1]);
@@ -86,16 +89,16 @@ i32 run_main_loop(void) {
handle_ui_events(&(comp.windows[comp.active_window - 1]), &(comp.ctx),
&(comp.event));
switch (comp.event.type) {
case SDL_QUIT:
if (comp.event.type == SDL_QUIT) {
comp.running = false;
break;
case SDL_WINDOWEVENT:
switch (comp.event.window.event) {
case SDL_WINDOWEVENT_CLOSE:
}
if (comp.event.type == SDL_WINDOWEVENT) {
if (comp.event.window.event == SDL_WINDOWEVENT_CLOSE) {
comp.running = false;
break;
case SDL_WINDOWEVENT_ENTER: {
}
if (comp.event.window.event == SDL_WINDOWEVENT_ENTER) {
u32 id = comp.event.window.windowID;
window *wnd = NULL;
@@ -109,29 +112,24 @@ i32 run_main_loop(void) {
}
}
if (!wnd) {
break;
if (wnd) {
SDL_RaiseWindow(wnd->window);
}
SDL_RaiseWindow(wnd->window);
break;
}
}
}
break;
case SDL_DROPFILE:
if (comp.event.type == SDL_DROPFILE) {
if (comp.event.drop.windowID == main_window->id) {
node_data data = (node_data){.path = comp.event.drop.file};
add_node(&comp, NODE_TYPE_IO, data, IO_INPUT_COUNT, comp.ctx.mouse_x,
comp.ctx.mouse_y, io_node_colours);
break;
}
}
}
update_node_graph(&comp, main_window);
for (u64 i = 0; i < MAX_WINDOWS; ++i) {
clear_window(&(comp.windows[i]), bg_colour);
}
@@ -152,10 +150,7 @@ i32 run_main_loop(void) {
}
}
for (u64 i = 0; i < comp.count; ++i) {
comp.nodes[i].node = ui_node(main_window, &(comp.ctx), comp.nodes[i].node,
comp.nodes[i].colours);
}
draw_node_graph(&comp, main_window);
for (u64 i = 0; i < MAX_WINDOWS; ++i) {
swap_buffers(&(comp.windows[i]));
@@ -175,34 +170,203 @@ i32 run_main_loop(void) {
return EXIT_SUCCESS;
}
void add_node(compositor *comp, node_type type, node_data data, u64 inputs,
i32 x, i32 y, ui_elem_colours colours) {
internal void add_node(compositor *comp, node_type type, node_data data,
u64 inputs, i32 x, i32 y, ui_elem_colours colours) {
if (comp->count + 1 >= MAX_NODES) {
return;
}
u64 alloc_size = inputs * sizeof(ui_noodle_elem);
ui_noodle_elem *noodles = mem_arena_alloc(comp->arena, alloc_size);
if (!noodles) {
u64 alloc_size = inputs * sizeof(noodle);
noodle *noodles = mem_arena_alloc(comp->arena, alloc_size);
noodle *back_noodles = mem_arena_alloc(comp->arena, alloc_size);
if (!noodles || !back_noodles) {
return;
}
ui_node_elem elem = {
.rec =
(rect){
.topleft.x = x,
.topleft.y = y,
.w = NODE_WIDTH,
.h = NODE_HEIGHT,
},
.inputs = inputs,
.noodles = noodles,
u64 connected_alloc_size = MAX_NODES * sizeof(noodle *);
noodle **connected_noodles =
mem_arena_alloc(comp->arena, connected_alloc_size);
noodle **connected_back_noodles =
mem_arena_alloc(comp->arena, connected_alloc_size);
if (!connected_noodles || !connected_back_noodles) {
return;
}
rect rec = (rect){
.topleft.x = x,
.topleft.y = y,
.w = NODE_WIDTH,
.h = NODE_HEIGHT,
};
comp->nodes[(comp->count)++] = (node){
.node = elem,
u64 idx = ++(comp->count);
comp->nodes[idx] = comp->back_nodes[idx] = (node){
.rec = rec,
.colours = colours,
.type = type,
.data.path = data.path,
.inputs = inputs,
.connected = 0,
.noodles = noodles,
.connected_noodles = connected_noodles,
};
comp->back_nodes[idx].noodles = back_noodles;
comp->back_nodes[idx].connected_noodles = connected_back_noodles;
}
internal void update_node_graph(compositor *comp, const window *wnd) {
for (u64 i = NODE_START; i <= comp->count; ++i) {
node *node_elem = &(comp->nodes[i]);
const node *back_node = &(comp->back_nodes[i]);
node_elem->rec = back_node->rec;
node_elem->connected = back_node->connected;
for (u64 j = 0; j < node_elem->inputs; ++j) {
noodle *ndl = &(node_elem->noodles[j]);
const noodle *back_ndl = &(back_node->noodles[j]);
*ndl = *back_ndl;
}
for (u64 j = CONNECTION_START; j <= back_node->connected; ++j) {
node_elem->connected_noodles[j] = back_node->connected_noodles[j];
}
}
}
internal void draw_node_graph(compositor *comp, const window *wnd) {
for (u64 i = NODE_START; i <= comp->count; ++i) {
node *node_elem = &(comp->nodes[i]);
node *back_node = &(comp->back_nodes[i]);
f64 angle = 90.0;
f64 angle_delta = 25.0;
i64 delta_multiplier = node_elem->inputs % 2 == 0 ? -1 : 0;
for (u64 j = 0; j < node_elem->inputs; ++j) {
f64 new_angle = angle + angle_delta * delta_multiplier;
noodle *ndl = &(node_elem->noodles[j]);
noodle *back_ndl = &(back_node->noodles[j]);
if (ndl->ln.p0.x == ndl->ln.p1.x && ndl->ln.p0.y == ndl->ln.p1.y) {
point origin = {node_elem->rec.topleft.x + node_elem->rec.w / 2,
node_elem->rec.topleft.y + node_elem->rec.h / 2};
back_ndl->ln =
line_from_origin(origin, new_angle, DEFAULT_NOODLE_LENGTH);
}
switch (ui_noodle(wnd, &(comp->ctx), ndl->ln, node_elem->colours,
node_elem->rec)) {
case NOODLE_ACTION_DRAGGING:
back_ndl->ln.p0.x += comp->ctx.rel_x;
back_ndl->ln.p0.y += comp->ctx.rel_y;
break;
case NOODLE_ACTION_RELEASED: {
bool connected = false;
bool disconnect = false;
for (u64 k = NODE_START; k <= comp->count; ++k) {
if (k == i) {
continue;
}
const node *nd = &(comp->nodes[k]);
node *back_node = &(comp->back_nodes[k]);
if (aabb(nd->rec, comp->ctx.mouse_x, comp->ctx.mouse_y)) {
point p0 = {nd->rec.topleft.x + nd->rec.w / 2,
nd->rec.topleft.y + nd->rec.h / 2};
back_ndl->ln.p0 = p0;
connected = true;
disconnect = back_ndl->connected_node != EMPTY_NODE &&
back_ndl->connected_node != k;
if (back_ndl->connected_node != k) {
back_ndl->connected_node = k;
u64 idx = ++(back_node->connected);
back_ndl->connection_idx = idx;
back_node->connected_noodles[idx] = back_ndl;
}
break;
} else {
if (back_ndl->connected_node != EMPTY_NODE) {
disconnect = true;
}
}
}
if (disconnect) {
u64 conntection_idx = back_ndl->connection_idx;
u64 node_idx = back_ndl->connected_node;
node *connected_node = &(comp->back_nodes[node_idx]);
if (conntection_idx == connected_node->connected) {
connected_node->connected_noodles[conntection_idx] = NULL;
} else {
connected_node->connected_noodles[conntection_idx] =
connected_node->connected_noodles[connected_node->connected];
connected_node->connected_noodles[connected_node->connected] = NULL;
connected_node->connected_noodles[conntection_idx]->connection_idx =
conntection_idx;
}
connected_node->connected -= 1;
}
if (!connected) {
back_ndl->ln.p0 = ndl->ln.p1;
back_ndl->connected_node = EMPTY_NODE;
}
break;
}
default:
break;
}
if (delta_multiplier > 0) {
angle = new_angle;
}
if (delta_multiplier == 0) {
delta_multiplier = -1;
} else {
delta_multiplier *= -1;
}
}
if (ui_node(wnd, &(comp->ctx), node_elem->rec, node_elem->colours)) {
back_node->rec.topleft.x += comp->ctx.rel_x;
back_node->rec.topleft.y += comp->ctx.rel_y;
for (u64 j = 0; j < node_elem->inputs; ++j) {
noodle *ndl = &(node_elem->noodles[j]);
noodle *back_ndl = &(back_node->noodles[j]);
if (ndl->connected_node == EMPTY_NODE) {
back_ndl->ln.p0.x += comp->ctx.rel_x;
back_ndl->ln.p0.y += comp->ctx.rel_y;
}
back_ndl->ln.p1.x += comp->ctx.rel_x;
back_ndl->ln.p1.y += comp->ctx.rel_y;
}
for (u64 j = CONNECTION_START; j <= back_node->connected; ++j) {
noodle *ndl = back_node->connected_noodles[j];
ndl->ln.p0.x += comp->ctx.rel_x;
ndl->ln.p0.y += comp->ctx.rel_y;
}
}
}
}

186
src/ui.c
View File

@@ -8,14 +8,8 @@
#include <stdlib.h>
#define NOODLE_HALF_WIDTH 2
#define DEFAULT_NOODLE_LENGTH 60
internal u64 get_id(ui_ctx *ctx);
internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
ui_noodle_elem noodle,
ui_elem_colours colours, u64 parent_id);
internal bool aabb(rect rec, i32 x, i32 y);
internal line line_from_origin(point origin, f64 angle, i32 line_length);
void init_ui_ctx(ui_ctx *ctx) {
*ctx = (ui_ctx){0};
@@ -32,34 +26,31 @@ void reset_ui_ctx(ui_ctx *ctx) {
}
void handle_ui_events(const window *wnd, ui_ctx *ctx, const SDL_Event *event) {
switch (event->type) {
case SDL_MOUSEMOTION:
if (event->type == SDL_MOUSEMOTION) {
if (wnd->id == event->motion.windowID) {
ctx->mouse_x = event->motion.x;
ctx->mouse_y = event->motion.y;
ctx->rel_x += event->motion.xrel;
ctx->rel_y += event->motion.yrel;
ctx->wnd = wnd;
break;
}
case SDL_MOUSEBUTTONDOWN:
}
if (event->type == SDL_MOUSEBUTTONDOWN) {
if (wnd->id == event->button.windowID) {
ctx->mouse_x = event->button.x;
ctx->mouse_y = event->button.y;
ctx->mouse_down = true;
ctx->wnd = wnd;
break;
}
case SDL_MOUSEBUTTONUP:
}
if (event->type == SDL_MOUSEBUTTONUP) {
if (wnd->id == event->button.windowID) {
ctx->mouse_x = event->button.x;
ctx->mouse_y = event->button.y;
ctx->mouse_up = true;
ctx->wnd = wnd;
break;
}
}
}
@@ -102,55 +93,24 @@ bool ui_button(const window *wnd, ui_ctx *ctx, rect rec,
return false;
}
ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
ui_elem_colours colours) {
bool ui_node(const window *wnd, ui_ctx *ctx, rect rect,
ui_elem_colours colours) {
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
return (ui_node_elem){0};
return false;
}
u64 id = get_id(ctx);
ctx->elements[id] = (ui_elem){
.id = id,
.rec = node.rec,
.rec = rect,
.type = UI_ELEM_NODE,
};
f64 angle = 90.0;
f64 angle_delta = 25.0;
i64 delta_multiplier = node.inputs % 2 == 0 ? -1 : 0;
for (u64 i = 0; i < node.inputs; ++i) {
f64 new_angle = angle + angle_delta * delta_multiplier;
if (node.noodles[i].noodle.p0.x == node.noodles[i].noodle.p1.x &&
node.noodles[i].noodle.p0.y == node.noodles[i].noodle.p1.y) {
point origin = {node.rec.topleft.x + node.rec.w / 2,
node.rec.topleft.y + node.rec.h / 2};
node.noodles[i].noodle =
line_from_origin(origin, new_angle, DEFAULT_NOODLE_LENGTH);
} else {
node.noodles[i].noodle = node.noodles[i].noodle;
}
node.noodles[i] = ui_noodle(wnd, ctx, node.noodles[i], colours, id);
if (delta_multiplier > 0) {
angle = new_angle;
}
if (delta_multiplier == 0) {
delta_multiplier = -1;
} else {
delta_multiplier *= -1;
}
}
fill_rect(wnd, node.rec, colours.fill);
draw_rect(wnd, node.rec, colours.border);
fill_rect(wnd, rect, colours.fill);
draw_rect(wnd, rect, colours.border);
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
return node;
return false;
}
if (ctx->mouse_up) {
@@ -158,28 +118,15 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
ctx->hovered = ctx->active = -1;
}
return node;
return false;
}
if (ctx->hovered == id && ctx->active == id) {
node.rec.topleft.x += ctx->rel_x;
node.rec.topleft.y += ctx->rel_y;
for (u64 i = 0; i < node.inputs; ++i) {
if (node.noodles[i].connected_node == RESERVED_UI_SLOT) {
node.noodles[i].noodle.p0.x += ctx->rel_x;
node.noodles[i].noodle.p0.y += ctx->rel_y;
}
node.noodles[i].noodle.p1.x += ctx->rel_x;
node.noodles[i].noodle.p1.y += ctx->rel_y;
}
return node;
return true;
}
if (!aabb(node.rec, ctx->mouse_x, ctx->mouse_y)) {
return node;
if (!aabb(rect, ctx->mouse_x, ctx->mouse_y)) {
return false;
}
ctx->hovered = id;
@@ -188,55 +135,45 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
ctx->active = id;
}
return node;
return false;
}
internal u64 get_id(ui_ctx *ctx) {
// This will always keep the 0 slot empty
return ++(ctx->count);
}
internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
ui_noodle_elem noodle,
ui_elem_colours colours, u64 parent_id) {
noodle_action ui_noodle(const window *wnd, ui_ctx *ctx, line ln,
ui_elem_colours colours, rect parent_node) {
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
return (ui_noodle_elem){0};
return NOODLE_ACTION_NONE;
}
u64 id = get_id(ctx);
ctx->elements[id] = (ui_elem){
.id = id,
.ln = noodle.noodle,
.ln = ln,
.type = UI_ELEM_NOODLE,
};
bool horizontal = noodle.noodle.p0.y == noodle.noodle.p1.y;
bool horizontal = ln.p0.y == ln.p1.y;
rect bounding_box = (rect){0};
if (horizontal) {
i32 x = min(noodle.noodle.p0.x, noodle.noodle.p1.x);
i32 x = min(ln.p0.x, ln.p1.x);
bounding_box.topleft = (point){x, noodle.noodle.p0.y - NOODLE_HALF_WIDTH};
bounding_box.w = abs(noodle.noodle.p1.x - noodle.noodle.p0.x);
bounding_box.topleft = (point){x, ln.p0.y - NOODLE_HALF_WIDTH};
bounding_box.w = abs(ln.p1.x - ln.p0.x);
bounding_box.h = NOODLE_HALF_WIDTH * 2;
fill_rect(wnd, bounding_box, colours.fill);
} else {
vec2 direction = line_direction(&noodle.noodle);
vec2 direction = line_direction(&ln);
quad qd = (quad){0};
if (direction.x == 0) {
qd = (quad){
.p0 = (point){noodle.noodle.p0.x - NOODLE_HALF_WIDTH,
noodle.noodle.p0.y},
.p1 = (point){noodle.noodle.p0.x + NOODLE_HALF_WIDTH,
noodle.noodle.p0.y},
.p2 = (point){noodle.noodle.p1.x - NOODLE_HALF_WIDTH,
noodle.noodle.p1.y},
.p3 = (point){noodle.noodle.p1.x + NOODLE_HALF_WIDTH,
noodle.noodle.p1.y},
.p0 = (point){ln.p0.x - NOODLE_HALF_WIDTH, ln.p0.y},
.p1 = (point){ln.p0.x + NOODLE_HALF_WIDTH, ln.p0.y},
.p2 = (point){ln.p1.x - NOODLE_HALF_WIDTH, ln.p1.y},
.p3 = (point){ln.p1.x + NOODLE_HALF_WIDTH, ln.p1.y},
};
} else {
f32 slope = (f32)(direction.y) / direction.x;
@@ -246,14 +183,10 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
f32 perpendicular_dx = -1.0f * slope * perpendicular_dy;
qd = (quad){
.p0 = (point){noodle.noodle.p0.x - perpendicular_dx,
noodle.noodle.p0.y - perpendicular_dy},
.p1 = (point){noodle.noodle.p0.x + perpendicular_dx,
noodle.noodle.p0.y + perpendicular_dy},
.p2 = (point){noodle.noodle.p1.x - perpendicular_dx,
noodle.noodle.p1.y - perpendicular_dy},
.p3 = (point){noodle.noodle.p1.x + perpendicular_dx,
noodle.noodle.p1.y + perpendicular_dy},
.p0 = (point){ln.p0.x - perpendicular_dx, ln.p0.y - perpendicular_dy},
.p1 = (point){ln.p0.x + perpendicular_dx, ln.p0.y + perpendicular_dy},
.p2 = (point){ln.p1.x - perpendicular_dx, ln.p1.y - perpendicular_dy},
.p3 = (point){ln.p1.x + perpendicular_dx, ln.p1.y + perpendicular_dy},
};
}
@@ -284,39 +217,25 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
}
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
return noodle;
return NOODLE_ACTION_NONE;
}
if (ctx->mouse_up) {
if (ctx->hovered == ctx->active && ctx->hovered == id) {
ctx->hovered = ctx->active = -1;
return NOODLE_ACTION_RELEASED;
}
if (noodle.connected_node > RESERVED_UI_SLOT) {
return noodle;
}
line updated_noodle = (line){
.p0 = noodle.noodle.p1,
.p1 = noodle.noodle.p1,
};
return (ui_noodle_elem){
.noodle = updated_noodle,
.connected_node = noodle.connected_node,
};
return NOODLE_ACTION_NONE;
}
if (ctx->hovered == id && ctx->active == id) {
noodle.noodle.p0.x += ctx->rel_x;
noodle.noodle.p0.y += ctx->rel_y;
return noodle;
return NOODLE_ACTION_DRAGGING;
}
const rect *node = &(ctx->elements[parent_id].rec);
if (!aabb(bounding_box, ctx->mouse_x, ctx->mouse_y) ||
aabb(*node, ctx->mouse_x, ctx->mouse_y)) {
return noodle;
aabb(parent_node, ctx->mouse_x, ctx->mouse_y)) {
return NOODLE_ACTION_NONE;
}
ctx->hovered = id;
@@ -325,23 +244,10 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
ctx->active = id;
}
return noodle;
return NOODLE_ACTION_NONE;
}
internal bool aabb(rect rec, i32 x, i32 y) {
return x > rec.topleft.x && x <= rec.topleft.x + rec.w && y > rec.topleft.y &&
y <= rec.topleft.y + rec.h;
}
internal line line_from_origin(point origin, f64 angle, i32 line_length) {
f64 rad = radians(angle);
f64 direction = angle / absolute(angle) * -1;
i32 adjacent = line_length * cos(rad) * direction; // dx
i32 opposite = line_length * sin(rad) * direction; // dy
return (line){
(point){origin.x + adjacent, origin.y + opposite},
origin,
};
internal u64 get_id(ui_ctx *ctx) {
// This will always keep the 0 slot empty
return ++(ctx->count);
}

View File

@@ -162,6 +162,24 @@ void fill_quad(const window *wnd, quad qd, colour colour) {
fill_triangle(wnd, t1, colour);
}
line line_from_origin(point origin, f64 angle, i32 line_length) {
f64 rad = radians(angle);
f64 direction = angle / absolute(angle) * -1;
i32 adjacent = line_length * cos(rad) * direction; // dx
i32 opposite = line_length * sin(rad) * direction; // dy
return (line){
(point){origin.x + adjacent, origin.y + opposite},
origin,
};
}
bool aabb(rect rec, i32 x, i32 y) {
return x > rec.topleft.x && x <= rec.topleft.x + rec.w && y > rec.topleft.y &&
y <= rec.topleft.y + rec.h;
}
internal inline bool inside_triangle(triangle tri, point p) {
// Based on the following video:
// https://www.youtube.com/watch?v=HYAgJN3x4GA