diff --git a/include/nodes.h b/include/nodes.h index cd8f8b2..0a313b1 100644 --- a/include/nodes.h +++ b/include/nodes.h @@ -5,6 +5,8 @@ #include "ui.h" #define MAX_NODES 1024 +#define IO_INPUT_COUNT 0 +#define OP_INPUT_COUNT 2 typedef i32 (*node_func)(i32 a, i32 b); typedef enum node_type node_type; @@ -28,6 +30,7 @@ struct node { ui_elem_colours colours; node_type type; node_data data; + u64 inputs; }; #endif // !NODES_H diff --git a/include/ui.h b/include/ui.h index 92bd9e7..ba6be45 100644 --- a/include/ui.h +++ b/include/ui.h @@ -39,8 +39,9 @@ struct ui_elem_colours { typedef struct ui_node_elem ui_node_elem; struct ui_node_elem { - line noodle; rect rec; + line *noodles; + u64 inputs; }; struct ui_ctx { diff --git a/src/compositor.c b/src/compositor.c index 342cbcb..bf3ec4d 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -32,8 +32,8 @@ struct compositor { ui_ctx ctx; }; -void add_node(compositor *comp, node_type type, node_data data, i32 x, i32 y, - ui_elem_colours colours); +void add_node(compositor *comp, node_type type, node_data data, u64 inputs, + i32 x, i32 y, ui_elem_colours colours); i32 run_main_loop(void) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { @@ -124,8 +124,8 @@ i32 run_main_loop(void) { if (comp.event.drop.windowID == main_window->id) { node_data data = (node_data){.path = comp.event.drop.file}; - add_node(&comp, NODEYPE_IO, data, comp.ctx.mouse_x, comp.ctx.mouse_y, - io_node_colours); + add_node(&comp, NODEYPE_IO, data, IO_INPUT_COUNT, comp.ctx.mouse_x, + comp.ctx.mouse_y, io_node_colours); break; } @@ -147,8 +147,8 @@ i32 run_main_loop(void) { if (ui_button(toolbox, &(comp.ctx), rect, button_colours)) { node_data data = (node_data){.func = ops[i]}; - add_node(&comp, NODEYPE_OP, data, comp.ctx.mouse_x, comp.ctx.mouse_y, - op_node_colours); + add_node(&comp, NODEYPE_OP, data, OP_INPUT_COUNT, comp.ctx.mouse_x, + comp.ctx.mouse_y, op_node_colours); } } @@ -175,24 +175,31 @@ i32 run_main_loop(void) { return EXIT_SUCCESS; } -void add_node(compositor *comp, node_type type, node_data data, i32 x, i32 y, - ui_elem_colours colours) { +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; } - comp->nodes[(comp->count)++] = (node){ - .node = - (ui_node_elem){ - .rec = - (rect){ - .topleft.x = x, - .topleft.y = y, - .w = NODE_WIDTH, - .h = NODE_HEIGHT, - }, - .noodle = (line){0}, + line *noodles = mem_arena_alloc(comp->arena, inputs * sizeof(line)); + if (!noodles) { + return; + } + + ui_node_elem elem = { + .rec = + (rect){ + .topleft.x = x, + .topleft.y = y, + .w = NODE_WIDTH, + .h = NODE_HEIGHT, }, + .inputs = inputs, + .noodles = noodles, + }; + + comp->nodes[(comp->count)++] = (node){ + .node = elem, .colours = colours, .type = type, .data.path = data.path, diff --git a/src/ui.c b/src/ui.c index b342a2f..9b6b500 100644 --- a/src/ui.c +++ b/src/ui.c @@ -10,8 +10,8 @@ #define NOODLE_HALF_WIDTH 2 #define DEFAULT_NOODLE_LENGTH 60 -line ui_noodle(const window *wnd, ui_ctx *ctx, line ln, - ui_elem_colours colours); +internal line ui_noodle(const window *wnd, ui_ctx *ctx, line ln, + ui_elem_colours colours, rect node); internal bool aabb(rect rec, i32 x, i32 y); internal line line_from_origin(point origin, f64 angle, i32 line_length); @@ -103,17 +103,36 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node, u64 id = (ctx->count)++; - line ln; - if (node.noodle.p0.x == node.noodle.p1.x && - node.noodle.p0.y == node.noodle.p1.y) { - ln = line_from_origin((point){node.rec.topleft.x + node.rec.w / 2, - node.rec.topleft.y + node.rec.h / 2}, - 90.0, DEFAULT_NOODLE_LENGTH); - } else { - ln = node.noodle; - } + line ln = {0}; + f64 angle = 90.0; + f64 angle_delta = 25.0; + i64 delta_multiplier = node.inputs % 2 == 0 ? -1 : 0; - node.noodle = ui_noodle(wnd, ctx, ln, colours); + for (u64 i = 0; i < node.inputs; ++i) { + if (node.noodles[i].p0.x == node.noodles[i].p1.x && + node.noodles[i].p0.y == node.noodles[i].p1.y) { + point origin = {node.rec.topleft.x + node.rec.w / 2, + node.rec.topleft.y + node.rec.h / 2}; + + f64 new_angle = angle + angle_delta * delta_multiplier; + + ln = line_from_origin(origin, new_angle, DEFAULT_NOODLE_LENGTH); + + if (delta_multiplier > 0) { + angle = new_angle; + } + + if (delta_multiplier == 0) { + delta_multiplier = -1; + } else { + delta_multiplier *= -1; + } + } else { + ln = node.noodles[i]; + } + + node.noodles[i] = ui_noodle(wnd, ctx, ln, colours, node.rec); + } fill_rect(wnd, node.rec, colours.fill); draw_rect(wnd, node.rec, colours.border); @@ -131,10 +150,13 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node, if (ctx->hovered == id && ctx->active == id) { node.rec.topleft.x += ctx->rel_x; node.rec.topleft.y += ctx->rel_y; - node.noodle.p0.x += ctx->rel_x; - node.noodle.p0.y += ctx->rel_y; - node.noodle.p1.x += ctx->rel_x; - node.noodle.p1.y += ctx->rel_y; + + for (u64 i = 0; i < node.inputs; ++i) { + node.noodles[i].p0.x += ctx->rel_x; + node.noodles[i].p0.y += ctx->rel_y; + node.noodles[i].p1.x += ctx->rel_x; + node.noodles[i].p1.y += ctx->rel_y; + } return node; } @@ -152,8 +174,8 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node, return node; } -line ui_noodle(const window *wnd, ui_ctx *ctx, line ln, - ui_elem_colours colours) { +internal line ui_noodle(const window *wnd, ui_ctx *ctx, line ln, + ui_elem_colours colours, rect node) { if (ctx->count + 1 >= MAX_UI_ELEMENTS) { return (line){0}; } @@ -242,7 +264,8 @@ line ui_noodle(const window *wnd, ui_ctx *ctx, line ln, return ln; } - if (!aabb(bounding_box, ctx->mouse_x, ctx->mouse_y)) { + if (!aabb(bounding_box, ctx->mouse_x, ctx->mouse_y) || + aabb(node, ctx->mouse_x, ctx->mouse_y)) { return ln; }