Simplify the immediate mode functions and move node
connection logic to the application level
This commit is contained in:
parent
bc6bb1afdc
commit
7b7a913c46
19
include/ui.h
19
include/ui.h
@ -16,6 +16,8 @@
|
|||||||
#define NODE_WIDTH 70
|
#define NODE_WIDTH 70
|
||||||
#define NODE_HEIGHT 20
|
#define NODE_HEIGHT 20
|
||||||
|
|
||||||
|
#define DEFAULT_NOODLE_LENGTH 60
|
||||||
|
|
||||||
typedef enum ui_elem_type ui_elem_type;
|
typedef enum ui_elem_type ui_elem_type;
|
||||||
typedef struct ui_elem ui_elem;
|
typedef struct ui_elem ui_elem;
|
||||||
typedef struct ui_ctx ui_ctx;
|
typedef struct ui_ctx ui_ctx;
|
||||||
@ -43,19 +45,6 @@ struct ui_elem_colours {
|
|||||||
colour border;
|
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ui_ctx {
|
struct ui_ctx {
|
||||||
u64 count;
|
u64 count;
|
||||||
i64 hovered;
|
i64 hovered;
|
||||||
@ -75,7 +64,9 @@ void reset_ui_ctx(ui_ctx *ctx);
|
|||||||
void handle_ui_events(const window *wnd, ui_ctx *ctx, const SDL_Event *event);
|
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,
|
bool ui_button(const window *wnd, ui_ctx *ctx, rect rect,
|
||||||
ui_elem_colours colours);
|
ui_elem_colours colours);
|
||||||
ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
|
bool ui_node(const window *wnd, ui_ctx *ctx, rect rect,
|
||||||
ui_elem_colours colours);
|
ui_elem_colours colours);
|
||||||
|
bool ui_noodle(const window *wnd, ui_ctx *ctx, line ln, ui_elem_colours colours,
|
||||||
|
rect parent_node);
|
||||||
|
|
||||||
#endif // !UI_H
|
#endif // !UI_H
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <SDL2/SDL_render.h>
|
#include <SDL2/SDL_render.h>
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define MAX_WINDOWS 2
|
#define MAX_WINDOWS 2
|
||||||
@ -153,8 +154,54 @@ i32 run_main_loop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < comp.count; ++i) {
|
for (u64 i = 0; i < comp.count; ++i) {
|
||||||
comp.nodes[i].node = ui_node(main_window, &(comp.ctx), comp.nodes[i].node,
|
node *node_elem = &(comp.nodes[i]);
|
||||||
comp.nodes[i].colours);
|
|
||||||
|
f64 angle = 90.0;
|
||||||
|
f64 angle_delta = 25.0;
|
||||||
|
i64 delta_multiplier = node_elem->inputs % 2 == 0 ? -1 : 0;
|
||||||
|
|
||||||
|
for (u64 j = 0; j < comp.nodes[i].inputs; ++j) {
|
||||||
|
f64 new_angle = angle + angle_delta * delta_multiplier;
|
||||||
|
line *ln = &(node_elem->noodles[j]);
|
||||||
|
|
||||||
|
if (ln->p0.x == ln->p1.x && ln->p0.y == 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};
|
||||||
|
|
||||||
|
*ln = line_from_origin(origin, new_angle, DEFAULT_NOODLE_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui_noodle(main_window, &(comp.ctx), *ln, node_elem->colours,
|
||||||
|
node_elem->rec)) {
|
||||||
|
ln->p0.x += comp.ctx.rel_x;
|
||||||
|
ln->p0.y += comp.ctx.rel_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta_multiplier > 0) {
|
||||||
|
angle = new_angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta_multiplier == 0) {
|
||||||
|
delta_multiplier = -1;
|
||||||
|
} else {
|
||||||
|
delta_multiplier *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui_node(main_window, &(comp.ctx), node_elem->rec,
|
||||||
|
node_elem->colours)) {
|
||||||
|
node_elem->rec.topleft.x += comp.ctx.rel_x;
|
||||||
|
node_elem->rec.topleft.y += comp.ctx.rel_y;
|
||||||
|
|
||||||
|
for (u64 j = 0; j < comp.nodes[i].inputs; ++j) {
|
||||||
|
line *ln = &(node_elem->noodles[j]);
|
||||||
|
|
||||||
|
ln->p0.x += comp.ctx.rel_x;
|
||||||
|
ln->p0.y += comp.ctx.rel_y;
|
||||||
|
ln->p1.x += comp.ctx.rel_x;
|
||||||
|
ln->p1.y += comp.ctx.rel_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < MAX_WINDOWS; ++i) {
|
for (u64 i = 0; i < MAX_WINDOWS; ++i) {
|
||||||
@ -181,28 +228,25 @@ void add_node(compositor *comp, node_type type, node_data data, u64 inputs,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 alloc_size = inputs * sizeof(ui_noodle_elem);
|
u64 alloc_size = inputs * sizeof(line);
|
||||||
ui_noodle_elem *noodles = mem_arena_alloc(comp->arena, alloc_size);
|
line *noodles = mem_arena_alloc(comp->arena, alloc_size);
|
||||||
if (!noodles) {
|
if (!noodles) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_node_elem elem = {
|
rect rec = (rect){
|
||||||
.rec =
|
|
||||||
(rect){
|
|
||||||
.topleft.x = x,
|
.topleft.x = x,
|
||||||
.topleft.y = y,
|
.topleft.y = y,
|
||||||
.w = NODE_WIDTH,
|
.w = NODE_WIDTH,
|
||||||
.h = NODE_HEIGHT,
|
.h = NODE_HEIGHT,
|
||||||
},
|
|
||||||
.inputs = inputs,
|
|
||||||
.noodles = noodles,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
comp->nodes[(comp->count)++] = (node){
|
comp->nodes[(comp->count)++] = (node){
|
||||||
.node = elem,
|
.rec = rec,
|
||||||
.colours = colours,
|
.colours = colours,
|
||||||
.type = type,
|
.type = type,
|
||||||
.data.path = data.path,
|
.data.path = data.path,
|
||||||
|
.inputs = inputs,
|
||||||
|
.noodles = noodles,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
160
src/ui.c
160
src/ui.c
@ -8,14 +8,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define NOODLE_HALF_WIDTH 2
|
#define NOODLE_HALF_WIDTH 2
|
||||||
#define DEFAULT_NOODLE_LENGTH 60
|
|
||||||
|
|
||||||
internal u64 get_id(ui_ctx *ctx);
|
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) {
|
void init_ui_ctx(ui_ctx *ctx) {
|
||||||
*ctx = (ui_ctx){0};
|
*ctx = (ui_ctx){0};
|
||||||
@ -102,55 +96,24 @@ bool ui_button(const window *wnd, ui_ctx *ctx, rect rec,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
|
bool ui_node(const window *wnd, ui_ctx *ctx, rect rect,
|
||||||
ui_elem_colours colours) {
|
ui_elem_colours colours) {
|
||||||
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
|
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
|
||||||
return (ui_node_elem){0};
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 id = get_id(ctx);
|
u64 id = get_id(ctx);
|
||||||
ctx->elements[id] = (ui_elem){
|
ctx->elements[id] = (ui_elem){
|
||||||
.id = id,
|
.id = id,
|
||||||
.rec = node.rec,
|
.rec = rect,
|
||||||
.type = UI_ELEM_NODE,
|
.type = UI_ELEM_NODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
f64 angle = 90.0;
|
fill_rect(wnd, rect, colours.fill);
|
||||||
f64 angle_delta = 25.0;
|
draw_rect(wnd, rect, colours.border);
|
||||||
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);
|
|
||||||
|
|
||||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
||||||
return node;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->mouse_up) {
|
if (ctx->mouse_up) {
|
||||||
@ -158,28 +121,15 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
|
|||||||
ctx->hovered = ctx->active = -1;
|
ctx->hovered = ctx->active = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->hovered == id && ctx->active == id) {
|
if (ctx->hovered == id && ctx->active == id) {
|
||||||
node.rec.topleft.x += ctx->rel_x;
|
return true;
|
||||||
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;
|
if (!aabb(rect, ctx->mouse_x, ctx->mouse_y)) {
|
||||||
node.noodles[i].noodle.p1.y += ctx->rel_y;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aabb(node.rec, ctx->mouse_x, ctx->mouse_y)) {
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->hovered = id;
|
ctx->hovered = id;
|
||||||
@ -188,7 +138,7 @@ ui_node_elem ui_node(const window *wnd, ui_ctx *ctx, ui_node_elem node,
|
|||||||
ctx->active = id;
|
ctx->active = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u64 get_id(ui_ctx *ctx) {
|
internal u64 get_id(ui_ctx *ctx) {
|
||||||
@ -196,47 +146,42 @@ internal u64 get_id(ui_ctx *ctx) {
|
|||||||
return ++(ctx->count);
|
return ++(ctx->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
|
bool ui_noodle(const window *wnd, ui_ctx *ctx, line ln, ui_elem_colours colours,
|
||||||
ui_noodle_elem noodle,
|
rect parent_node) {
|
||||||
ui_elem_colours colours, u64 parent_id) {
|
|
||||||
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
|
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
|
||||||
return (ui_noodle_elem){0};
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 id = get_id(ctx);
|
u64 id = get_id(ctx);
|
||||||
ctx->elements[id] = (ui_elem){
|
ctx->elements[id] = (ui_elem){
|
||||||
.id = id,
|
.id = id,
|
||||||
.ln = noodle.noodle,
|
.ln = ln,
|
||||||
.type = UI_ELEM_NOODLE,
|
.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};
|
rect bounding_box = (rect){0};
|
||||||
|
|
||||||
if (horizontal) {
|
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.topleft = (point){x, ln.p0.y - NOODLE_HALF_WIDTH};
|
||||||
bounding_box.w = abs(noodle.noodle.p1.x - noodle.noodle.p0.x);
|
bounding_box.w = abs(ln.p1.x - ln.p0.x);
|
||||||
bounding_box.h = NOODLE_HALF_WIDTH * 2;
|
bounding_box.h = NOODLE_HALF_WIDTH * 2;
|
||||||
|
|
||||||
fill_rect(wnd, bounding_box, colours.fill);
|
fill_rect(wnd, bounding_box, colours.fill);
|
||||||
} else {
|
} else {
|
||||||
vec2 direction = line_direction(&noodle.noodle);
|
vec2 direction = line_direction(&ln);
|
||||||
|
|
||||||
quad qd = (quad){0};
|
quad qd = (quad){0};
|
||||||
|
|
||||||
if (direction.x == 0) {
|
if (direction.x == 0) {
|
||||||
qd = (quad){
|
qd = (quad){
|
||||||
.p0 = (point){noodle.noodle.p0.x - NOODLE_HALF_WIDTH,
|
.p0 = (point){ln.p0.x - NOODLE_HALF_WIDTH, ln.p0.y},
|
||||||
noodle.noodle.p0.y},
|
.p1 = (point){ln.p0.x + NOODLE_HALF_WIDTH, ln.p0.y},
|
||||||
.p1 = (point){noodle.noodle.p0.x + NOODLE_HALF_WIDTH,
|
.p2 = (point){ln.p1.x - NOODLE_HALF_WIDTH, ln.p1.y},
|
||||||
noodle.noodle.p0.y},
|
.p3 = (point){ln.p1.x + NOODLE_HALF_WIDTH, ln.p1.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},
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
f32 slope = (f32)(direction.y) / direction.x;
|
f32 slope = (f32)(direction.y) / direction.x;
|
||||||
@ -246,14 +191,10 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
|
|||||||
f32 perpendicular_dx = -1.0f * slope * perpendicular_dy;
|
f32 perpendicular_dx = -1.0f * slope * perpendicular_dy;
|
||||||
|
|
||||||
qd = (quad){
|
qd = (quad){
|
||||||
.p0 = (point){noodle.noodle.p0.x - perpendicular_dx,
|
.p0 = (point){ln.p0.x - perpendicular_dx, ln.p0.y - perpendicular_dy},
|
||||||
noodle.noodle.p0.y - perpendicular_dy},
|
.p1 = (point){ln.p0.x + perpendicular_dx, ln.p0.y + perpendicular_dy},
|
||||||
.p1 = (point){noodle.noodle.p0.x + perpendicular_dx,
|
.p2 = (point){ln.p1.x - perpendicular_dx, ln.p1.y - perpendicular_dy},
|
||||||
noodle.noodle.p0.y + perpendicular_dy},
|
.p3 = (point){ln.p1.x + perpendicular_dx, ln.p1.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},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +225,7 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
||||||
return noodle;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->mouse_up) {
|
if (ctx->mouse_up) {
|
||||||
@ -292,31 +233,16 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
|
|||||||
ctx->hovered = ctx->active = -1;
|
ctx->hovered = ctx->active = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noodle.connected_node > RESERVED_UI_SLOT) {
|
return true;
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->hovered == id && ctx->active == id) {
|
if (ctx->hovered == id && ctx->active == id) {
|
||||||
noodle.noodle.p0.x += ctx->rel_x;
|
return true;
|
||||||
noodle.noodle.p0.y += ctx->rel_y;
|
|
||||||
|
|
||||||
return noodle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rect *node = &(ctx->elements[parent_id].rec);
|
|
||||||
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)) {
|
aabb(parent_node, ctx->mouse_x, ctx->mouse_y)) {
|
||||||
return noodle;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->hovered = id;
|
ctx->hovered = id;
|
||||||
@ -325,23 +251,5 @@ internal ui_noodle_elem ui_noodle(const window *wnd, ui_ctx *ctx,
|
|||||||
ctx->active = id;
|
ctx->active = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return noodle;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user