diff --git a/include/nodes.h b/include/nodes.h index 74c3505..6756f2e 100644 --- a/include/nodes.h +++ b/include/nodes.h @@ -9,6 +9,7 @@ #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; @@ -31,6 +32,7 @@ union node_data { struct noodle { line ln; u64 connected_node; + u64 connection_idx; }; struct node { @@ -39,7 +41,9 @@ struct node { node_type type; node_data data; u64 inputs; + u64 connected; noodle *noodles; + noodle **connected_noodles; }; #endif // !NODES_H diff --git a/src/compositor.c b/src/compositor.c index ee1c79a..135f0c7 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -183,6 +183,15 @@ internal void add_node(compositor *comp, node_type type, node_data data, return; } + 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, @@ -198,10 +207,13 @@ internal void add_node(compositor *comp, node_type type, node_data data, .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) { @@ -210,13 +222,17 @@ internal void update_node_graph(compositor *comp, const window *wnd) { 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->connected_node = back_ndl->connected_node; - ndl->ln = back_ndl->ln; + *ndl = *back_ndl; + } + + for (u64 j = CONNECTION_START; j <= back_node->connected; ++j) { + node_elem->connected_noodles[j] = back_node->connected_noodles[j]; } } } @@ -251,6 +267,7 @@ internal void draw_node_graph(compositor *comp, const window *wnd) { break; case NOODLE_ACTION_RELEASED: { bool connected = false; + bool disconnect = false; for (u64 k = NODE_START; k <= comp->count; ++k) { if (k == i) { @@ -258,19 +275,53 @@ internal void draw_node_graph(compositor *comp, const window *wnd) { } 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; - back_ndl->connected_node = k; 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; @@ -310,23 +361,11 @@ internal void draw_node_graph(compositor *comp, const window *wnd) { back_ndl->ln.p1.y += comp->ctx.rel_y; } - for (u64 j = NODE_START; j <= comp->count; ++j) { - if (j == i) { - continue; - } + for (u64 j = CONNECTION_START; j <= back_node->connected; ++j) { + noodle *ndl = back_node->connected_noodles[j]; - node *nd = &(comp->back_nodes[j]); - if (nd->inputs == 0) { - continue; - } - - for (u64 k = 0; k < nd->inputs; ++k) { - noodle *ndl = &(nd->noodles[k]); - if (ndl->connected_node == i) { - ndl->ln.p0.x += comp->ctx.rel_x; - ndl->ln.p0.y += comp->ctx.rel_y; - } - } + ndl->ln.p0.x += comp->ctx.rel_x; + ndl->ln.p0.y += comp->ctx.rel_y; } } }