Compare commits
43 Commits
e71c144db6
...
main
Author | SHA1 | Date | |
---|---|---|---|
f419378183 | |||
46a4802ce6 | |||
4ed86611b5 | |||
|
b447e9d5a1 | ||
|
65d69bd570 | ||
9570f31dc7 | |||
547764764c | |||
29bcfabda9 | |||
f03dad33a2 | |||
8078a72deb | |||
f2faa56e5f | |||
a68d6997a5 | |||
373e48216d | |||
7b7a913c46 | |||
bc6bb1afdc | |||
b847f87ee5 | |||
4610561eff | |||
8501eb787e | |||
050bb355d0 | |||
a86b025f7d | |||
2d31233a1e | |||
30986e3c99 | |||
84cdb87a19 | |||
84873f1e98 | |||
10ba3d642d | |||
d73275f04c | |||
f56e6b1bb1 | |||
c70f252349 | |||
8275fce9c6 | |||
a58a315d48 | |||
04855478fd | |||
9139dae379 | |||
9f700c070d | |||
bdb4a52771 | |||
afd09d7742 | |||
924ed544aa | |||
f72497e1b7 | |||
b329e0feb4 | |||
53d0a4698f | |||
64f0328966 | |||
6df11cfdeb | |||
fa82203681 | |||
63f119c1b2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.cache
|
||||
compile_commands.json
|
||||
main
|
||||
*.dSYM
|
||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "intern/aliases"]
|
||||
path = intern/aliases
|
||||
url = https://git.thewizardapprentice.com/abdelrahman/c-cpp-aliases.git
|
||||
[submodule "intern/wizapp"]
|
||||
path = intern/wizapp
|
||||
url = https://git.thewizardapprentice.com/abdelrahman/wizapp-stdlib.git
|
||||
|
20
compile
20
compile
@@ -1,9 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
CC=clang
|
||||
CFLAGS="-g -Wall -Iinclude -Iintern $(pkg-config --cflags sdl2)"
|
||||
LIBS="$(pkg-config --libs sdl2)"
|
||||
SRC=src/*.c
|
||||
CFLAGS="-g -Wall $(pkg-config --cflags sdl2)"
|
||||
LIBS="$(pkg-config --libs sdl2) -lm"
|
||||
INCLUDE="\
|
||||
-Iinclude \
|
||||
-Iintern/wizapp/aliases \
|
||||
-Iintern/wizapp/cpath/include \
|
||||
-Iintern/wizapp/dstr/include \
|
||||
$(find intern/wizapp/mem/include -type d | xargs -I{} echo -n "-I{} ") \
|
||||
"
|
||||
SRC="\
|
||||
intern/wizapp/cpath/src/*.c \
|
||||
intern/wizapp/dstr/src/*.c \
|
||||
intern/wizapp/mem/src/*/*.c \
|
||||
src/*.c \
|
||||
"
|
||||
OUT=main
|
||||
|
||||
(set -x ; $CC $CFLAGS $LIBS $SRC -o $OUT)
|
||||
(set -x ; $CC $CFLAGS $INCLUDE $LIBS $SRC -o $OUT)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#ifndef COMPOSITOR_H
|
||||
#define COMPOSITOR_H
|
||||
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
|
||||
i32 run_main_loop(void);
|
||||
|
||||
|
14
include/math_utils.h
Normal file
14
include/math_utils.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef MATH_UTILS_H
|
||||
#define MATH_UTILS_H
|
||||
|
||||
#include "aliases.h"
|
||||
|
||||
#define square(x) (x * x)
|
||||
#define absolute(x) (x < 0.0 ? x * -1.0 : x)
|
||||
|
||||
i32 min(i32 a, i32 b);
|
||||
i32 max(i32 a, i32 b);
|
||||
f64 radians(f64 degrees);
|
||||
f64 degrees(f64 radians);
|
||||
|
||||
#endif // !MATH_UTILS_H
|
@@ -1,16 +1,21 @@
|
||||
#ifndef NODES_H
|
||||
#define NODES_H
|
||||
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "ui.h"
|
||||
#include "window.h"
|
||||
|
||||
#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_t)(i32 a, i32 b);
|
||||
typedef enum node_type node_type_t;
|
||||
typedef union node_data node_data_t;
|
||||
typedef struct node node_t;
|
||||
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,
|
||||
@@ -21,14 +26,24 @@ enum node_type {
|
||||
|
||||
union node_data {
|
||||
const char *path;
|
||||
node_func_t func;
|
||||
node_func func;
|
||||
};
|
||||
|
||||
struct noodle {
|
||||
line ln;
|
||||
u64 connected_node;
|
||||
u64 connection_idx;
|
||||
};
|
||||
|
||||
struct node {
|
||||
rect_t rect;
|
||||
ui_elem_colours_t colours;
|
||||
node_type_t type;
|
||||
node_data_t data;
|
||||
rect rec;
|
||||
ui_elem_colours colours;
|
||||
node_type type;
|
||||
node_data data;
|
||||
u64 inputs;
|
||||
u64 connected;
|
||||
noodle *noodles;
|
||||
noodle **connected_noodles;
|
||||
};
|
||||
|
||||
#endif // !NODES_H
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#ifndef COMP_OPS_H
|
||||
#define COMP_OPS_H
|
||||
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "nodes.h"
|
||||
|
||||
enum comp_ops {
|
||||
@@ -18,7 +18,7 @@ i32 comp_sub(i32 a, i32 b);
|
||||
i32 comp_mul(i32 a, i32 b);
|
||||
i32 comp_div(i32 a, i32 b);
|
||||
|
||||
INTERNAL node_func_t ops[COUNT_COMP_OPS] = {
|
||||
internal node_func ops[COUNT_COMP_OPS] = {
|
||||
[COMP_OP_ADD] = comp_add,
|
||||
[COMP_OP_SUB] = comp_sub,
|
||||
[COMP_OP_MUL] = comp_mul,
|
||||
|
54
include/ui.h
54
include/ui.h
@@ -2,11 +2,11 @@
|
||||
#define UI_H
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "window.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAX_UI_ELEMENTS 4096
|
||||
#define MAX_UI_ELEMENTS 8192
|
||||
|
||||
#define BUTTON_WIDTH 100
|
||||
#define BUTTON_HEIGHT 40
|
||||
@@ -14,12 +14,17 @@
|
||||
#define NODE_WIDTH 70
|
||||
#define NODE_HEIGHT 20
|
||||
|
||||
typedef enum ui_elem_type ui_elem_type_t;
|
||||
typedef struct ui_elem ui_elem_t;
|
||||
typedef struct ui_ctx ui_ctx_t;
|
||||
#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,
|
||||
UI_ELEM_NOODLE,
|
||||
UI_ELEM_BUTTON,
|
||||
|
||||
COUNT_UI_ELEM,
|
||||
@@ -27,14 +32,22 @@ enum ui_elem_type {
|
||||
|
||||
struct ui_elem {
|
||||
u64 id;
|
||||
rect_t rect;
|
||||
ui_elem_type_t type;
|
||||
union {
|
||||
rect rec;
|
||||
line ln;
|
||||
};
|
||||
ui_elem_type type;
|
||||
};
|
||||
|
||||
typedef struct ui_elem_colours ui_elem_colours_t;
|
||||
struct ui_elem_colours {
|
||||
colour_t fill;
|
||||
colour_t border;
|
||||
colour fill;
|
||||
colour border;
|
||||
};
|
||||
|
||||
enum noodle_action {
|
||||
NOODLE_ACTION_NONE,
|
||||
NOODLE_ACTION_DRAGGING,
|
||||
NOODLE_ACTION_RELEASED,
|
||||
};
|
||||
|
||||
struct ui_ctx {
|
||||
@@ -47,17 +60,18 @@ struct ui_ctx {
|
||||
i32 rel_y;
|
||||
bool mouse_down;
|
||||
bool mouse_up;
|
||||
const window_t *wnd;
|
||||
ui_elem_t elements[MAX_UI_ELEMENTS];
|
||||
const window *wnd;
|
||||
ui_elem elements[MAX_UI_ELEMENTS];
|
||||
};
|
||||
|
||||
void init_ui_ctx(ui_ctx_t *ctx);
|
||||
void reset_ui_ctx(ui_ctx_t *ctx);
|
||||
void handle_ui_events(const window_t *wnd, ui_ctx_t *ctx,
|
||||
const SDL_Event *event);
|
||||
bool button(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
|
||||
ui_elem_colours_t colours);
|
||||
rect_t node(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
|
||||
ui_elem_colours_t colours);
|
||||
void init_ui_ctx(ui_ctx *ctx);
|
||||
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);
|
||||
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
|
||||
|
@@ -1,17 +1,19 @@
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include <SDL2/SDL_pixels.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_video.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct point point_t;
|
||||
typedef struct line line_t;
|
||||
typedef struct triangle triangle_t;
|
||||
typedef struct rect rect_t;
|
||||
typedef struct window window_t;
|
||||
typedef struct point point;
|
||||
typedef point vec2;
|
||||
typedef struct line line;
|
||||
typedef struct triangle triangle;
|
||||
typedef struct quad quad;
|
||||
typedef struct rect rect;
|
||||
typedef struct window window;
|
||||
|
||||
struct point {
|
||||
i32 x;
|
||||
@@ -19,18 +21,25 @@ struct point {
|
||||
};
|
||||
|
||||
struct line {
|
||||
point_t p0;
|
||||
point_t p1;
|
||||
point p0;
|
||||
point p1;
|
||||
};
|
||||
|
||||
struct triangle {
|
||||
point_t p0;
|
||||
point_t p1;
|
||||
point_t p2;
|
||||
point p0;
|
||||
point p1;
|
||||
point p2;
|
||||
};
|
||||
|
||||
struct quad {
|
||||
point p0;
|
||||
point p1;
|
||||
point p2;
|
||||
point p3;
|
||||
};
|
||||
|
||||
struct rect {
|
||||
point_t topleft;
|
||||
point topleft;
|
||||
i32 w;
|
||||
i32 h;
|
||||
};
|
||||
@@ -46,7 +55,7 @@ struct window {
|
||||
SDL_Renderer *renderer;
|
||||
};
|
||||
|
||||
typedef struct colour colour_t;
|
||||
typedef struct colour colour;
|
||||
struct colour {
|
||||
union {
|
||||
u32 abgr;
|
||||
@@ -54,16 +63,24 @@ struct colour {
|
||||
};
|
||||
};
|
||||
|
||||
bool init_window(window_t *wnd, const char *title, u32 width, u32 height, i32 x,
|
||||
bool init_window(window *wnd, const char *title, u32 width, u32 height, i32 x,
|
||||
i32 y);
|
||||
void cleanup_window(window_t *wnd);
|
||||
void clear_window(const window_t *wnd, colour_t colour);
|
||||
void swap_buffers(const window_t *wnd);
|
||||
void draw_point(const window_t *wnd, point_t p, colour_t colour);
|
||||
void draw_line(const window_t *wnd, const line_t *ln, colour_t colour);
|
||||
void draw_triangle(const window_t *wnd, const triangle_t *triangle,
|
||||
colour_t colour);
|
||||
void draw_rect(const window_t *wnd, rect_t rect, colour_t colour);
|
||||
void fill_rect(const window_t *wnd, rect_t rect, colour_t colour);
|
||||
void cleanup_window(window *wnd);
|
||||
void clear_window(const window *wnd, colour colour);
|
||||
void swap_buffers(const window *wnd);
|
||||
|
||||
vec2 line_direction(const line *ln);
|
||||
|
||||
void draw_point(const window *wnd, point p, colour colour);
|
||||
void draw_line(const window *wnd, const line *ln, colour colour);
|
||||
void draw_triangle(const window *wnd, triangle triangle, colour colour);
|
||||
void draw_quad(const window *wnd, quad qd, colour colour);
|
||||
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
|
||||
|
Submodule intern/aliases deleted from f95f3aa499
1
intern/wizapp
Submodule
1
intern/wizapp
Submodule
Submodule intern/wizapp added at 7948d3fd1a
313
src/compositor.c
313
src/compositor.c
@@ -1,4 +1,5 @@
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "mem_arena.h"
|
||||
#include "nodes.h"
|
||||
#include "ops.h"
|
||||
#include "ui.h"
|
||||
@@ -15,35 +16,42 @@
|
||||
#define WINDOW_WIDTH 1280
|
||||
#define WINDOW_HEIGHT 720
|
||||
|
||||
typedef struct compositor compositor_t;
|
||||
#define ARENA_CAPACITY 1 * 1024 * 1024
|
||||
|
||||
typedef struct compositor compositor;
|
||||
struct compositor {
|
||||
window_t windows[MAX_WINDOWS];
|
||||
Arena *arena;
|
||||
window windows[MAX_WINDOWS];
|
||||
u32 active_window;
|
||||
SDL_Event event;
|
||||
bool running;
|
||||
i64 node_hovered;
|
||||
u64 count;
|
||||
node_t *nodes;
|
||||
bool move_node;
|
||||
ui_ctx_t ctx;
|
||||
node *nodes;
|
||||
node *back_nodes;
|
||||
ui_ctx ctx;
|
||||
};
|
||||
|
||||
void add_node(compositor_t *comp, node_type_t type, node_data_t data, i32 x,
|
||||
i32 y, ui_elem_colours_t 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) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
compositor_t comp = {0};
|
||||
compositor comp = {0};
|
||||
|
||||
init_ui_ctx(&(comp.ctx));
|
||||
mem_arena_init(&comp.arena, ARENA_CAPACITY);
|
||||
|
||||
comp.nodes = (node_t *)malloc(sizeof(node_t) * MAX_NODES);
|
||||
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_t *main_window = &(comp.windows[0]);
|
||||
window_t *toolbox = &(comp.windows[1]);
|
||||
window *main_window = &(comp.windows[0]);
|
||||
window *toolbox = &(comp.windows[1]);
|
||||
|
||||
if (!init_window(main_window, "Compositor", WINDOW_WIDTH, WINDOW_HEIGHT, -1,
|
||||
-1)) {
|
||||
@@ -60,18 +68,18 @@ i32 run_main_loop(void) {
|
||||
|
||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||
|
||||
colour_t bg_colour = {.abgr = 0xffffffff};
|
||||
ui_elem_colours_t button_colours = (ui_elem_colours_t){
|
||||
.fill = (colour_t){.abgr = 0xff89a83c},
|
||||
.border = (colour_t){.abgr = 0xff768432},
|
||||
colour bg_colour = {.abgr = 0xffffffff};
|
||||
ui_elem_colours button_colours = (ui_elem_colours){
|
||||
.fill = (colour){.abgr = 0xff89a83c},
|
||||
.border = (colour){.abgr = 0xff768432},
|
||||
};
|
||||
ui_elem_colours_t io_node_colours = (ui_elem_colours_t){
|
||||
.fill = (colour_t){.abgr = 0xff2c84b7},
|
||||
.border = (colour_t){.abgr = 0xff315c89},
|
||||
ui_elem_colours io_node_colours = (ui_elem_colours){
|
||||
.fill = (colour){.abgr = 0xff2c84b7},
|
||||
.border = (colour){.abgr = 0xff315c89},
|
||||
};
|
||||
ui_elem_colours_t op_node_colours = (ui_elem_colours_t){
|
||||
.fill = (colour_t){.abgr = 0xffad6c3a},
|
||||
.border = (colour_t){.abgr = 0xff8e4a33},
|
||||
ui_elem_colours op_node_colours = (ui_elem_colours){
|
||||
.fill = (colour){.abgr = 0xffad6c3a},
|
||||
.border = (colour){.abgr = 0xff8e4a33},
|
||||
};
|
||||
|
||||
i32 toolbox_button_x = (toolbox->width - BUTTON_WIDTH) / 2;
|
||||
@@ -81,21 +89,21 @@ 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_t *wnd = NULL;
|
||||
window *wnd = NULL;
|
||||
|
||||
for (u64 i = 0; i < MAX_WINDOWS; ++i) {
|
||||
window_t *window = &(comp.windows[i]);
|
||||
window *window = &(comp.windows[i]);
|
||||
|
||||
if (id == window->id) {
|
||||
comp.active_window = id;
|
||||
@@ -104,53 +112,45 @@ 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_t data = (node_data_t){.path = comp.event.drop.file};
|
||||
node_data data = (node_data){.path = comp.event.drop.file};
|
||||
|
||||
add_node(&comp, NODE_TYPE_IO, data, comp.ctx.mouse_x,
|
||||
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);
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < COUNT_COMP_OPS; ++i) {
|
||||
rect_t rect = {
|
||||
rect rect = {
|
||||
.topleft.x = toolbox_button_x,
|
||||
.topleft.y = i * (BUTTON_HEIGHT + 20) + 30,
|
||||
.w = BUTTON_WIDTH,
|
||||
.h = BUTTON_HEIGHT,
|
||||
};
|
||||
|
||||
if (button(toolbox, &(comp.ctx), rect, button_colours)) {
|
||||
node_data_t data = (node_data_t){.func = ops[i]};
|
||||
if (ui_button(toolbox, &(comp.ctx), rect, button_colours)) {
|
||||
node_data data = (node_data){.func = ops[i]};
|
||||
|
||||
add_node(&comp, NODE_TYPE_OP, data, comp.ctx.mouse_x, comp.ctx.mouse_y,
|
||||
op_node_colours);
|
||||
add_node(&comp, NODE_TYPE_OP, data, OP_INPUT_COUNT, comp.ctx.mouse_x,
|
||||
comp.ctx.mouse_y, op_node_colours);
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < comp.count; ++i) {
|
||||
comp.nodes[i].rect = node(main_window, &(comp.ctx), comp.nodes[i].rect,
|
||||
comp.nodes[i].colours);
|
||||
}
|
||||
draw_node_graph(&comp, main_window);
|
||||
|
||||
for (u64 i = 0; i < MAX_WINDOWS; ++i) {
|
||||
swap_buffers(&(comp.windows[i]));
|
||||
@@ -165,25 +165,208 @@ i32 run_main_loop(void) {
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
mem_arena_free(&comp.arena);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void add_node(compositor_t *comp, node_type_t type, node_data_t data, i32 x,
|
||||
i32 y, ui_elem_colours_t 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;
|
||||
}
|
||||
|
||||
comp->nodes[(comp->count)++] = (node_t){
|
||||
.rect =
|
||||
(rect_t){
|
||||
.topleft.x = x,
|
||||
.topleft.y = y,
|
||||
.w = NODE_WIDTH,
|
||||
.h = NODE_HEIGHT,
|
||||
},
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "compositor.h"
|
||||
|
||||
i32 main(void) { return run_main_loop(); }
|
||||
|
10
src/math_utils.c
Normal file
10
src/math_utils.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "math_utils.h"
|
||||
#include <math.h>
|
||||
|
||||
i32 min(i32 a, i32 b) { return a <= b ? a : b; }
|
||||
|
||||
i32 max(i32 a, i32 b) { return a >= b ? a : b; }
|
||||
|
||||
f64 radians(f64 degrees) { return degrees * M_PI / 180.0; }
|
||||
|
||||
f64 degrees(f64 radians) { return radians * 180.0 / M_PI; }
|
@@ -1,5 +1,5 @@
|
||||
#include "ops.h"
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
|
||||
i32 comp_add(i32 a, i32 b) { return a + b; }
|
||||
|
||||
|
224
src/ui.c
224
src/ui.c
@@ -1,87 +1,91 @@
|
||||
#include "ui.h"
|
||||
#include "SDL_events.h"
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "math_utils.h"
|
||||
#include "window.h"
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool aabb(const ui_elem_t *elem, i32 x, i32 y) {
|
||||
return x > elem->rect.topleft.x && x <= elem->rect.topleft.x + elem->rect.w &&
|
||||
y > elem->rect.topleft.y && y <= elem->rect.topleft.y + elem->rect.h;
|
||||
}
|
||||
#define NOODLE_HALF_WIDTH 2
|
||||
|
||||
void init_ui_ctx(ui_ctx_t *ctx) {
|
||||
*ctx = (ui_ctx_t){0};
|
||||
internal u64 get_id(ui_ctx *ctx);
|
||||
|
||||
void init_ui_ctx(ui_ctx *ctx) {
|
||||
*ctx = (ui_ctx){0};
|
||||
ctx->hovered = -1;
|
||||
ctx->active = -1;
|
||||
}
|
||||
|
||||
void reset_ui_ctx(ui_ctx_t *ctx) {
|
||||
void reset_ui_ctx(ui_ctx *ctx) {
|
||||
ctx->count = 0;
|
||||
ctx->mouse_down = false;
|
||||
ctx->mouse_up = false;
|
||||
ctx->rel_x = 0;
|
||||
ctx->rel_y = 0;
|
||||
}
|
||||
|
||||
void handle_ui_events(const window_t *wnd, ui_ctx_t *ctx,
|
||||
const SDL_Event *event) {
|
||||
switch (event->type) {
|
||||
case SDL_MOUSEMOTION:
|
||||
void handle_ui_events(const window *wnd, ui_ctx *ctx, const SDL_Event *event) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool button(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
|
||||
ui_elem_colours_t colours) {
|
||||
bool ui_button(const window *wnd, ui_ctx *ctx, rect rec,
|
||||
ui_elem_colours colours) {
|
||||
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui_elem_t elem = (ui_elem_t){
|
||||
.id = (ctx->count)++,
|
||||
.rect = rect,
|
||||
u64 id = get_id(ctx);
|
||||
ctx->elements[id] = (ui_elem){
|
||||
.id = id,
|
||||
.rec = rec,
|
||||
.type = UI_ELEM_BUTTON,
|
||||
};
|
||||
|
||||
fill_rect(wnd, rect, colours.fill);
|
||||
draw_rect(wnd, rect, colours.border);
|
||||
fill_rect(wnd, rec, colours.fill);
|
||||
draw_rect(wnd, rec, colours.border);
|
||||
|
||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != elem.id)) {
|
||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aabb(&elem, ctx->mouse_x, ctx->mouse_y)) {
|
||||
if (!aabb(rec, ctx->mouse_x, ctx->mouse_y)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->hovered = elem.id;
|
||||
ctx->hovered = id;
|
||||
|
||||
if (ctx->mouse_down) {
|
||||
ctx->active = elem.id;
|
||||
ctx->active = id;
|
||||
}
|
||||
|
||||
if (ctx->mouse_up && ctx->hovered == elem.id && ctx->active == elem.id) {
|
||||
if (ctx->mouse_up && ctx->hovered == id && ctx->active == id) {
|
||||
ctx->hovered = ctx->active = -1;
|
||||
return true;
|
||||
}
|
||||
@@ -89,51 +93,161 @@ bool button(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
|
||||
return false;
|
||||
}
|
||||
|
||||
rect_t node(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
|
||||
ui_elem_colours_t colours) {
|
||||
bool ui_node(const window *wnd, ui_ctx *ctx, rect rect,
|
||||
ui_elem_colours colours) {
|
||||
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
|
||||
return (rect_t){0};
|
||||
return false;
|
||||
}
|
||||
|
||||
ui_elem_t elem = (ui_elem_t){
|
||||
.id = (ctx->count)++,
|
||||
.rect = rect,
|
||||
u64 id = get_id(ctx);
|
||||
ctx->elements[id] = (ui_elem){
|
||||
.id = id,
|
||||
.rec = rect,
|
||||
.type = UI_ELEM_NODE,
|
||||
};
|
||||
|
||||
fill_rect(wnd, rect, colours.fill);
|
||||
draw_rect(wnd, rect, colours.border);
|
||||
|
||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != elem.id)) {
|
||||
return rect;
|
||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->mouse_up) {
|
||||
ctx->hovered = ctx->active = -1;
|
||||
ctx->rel_x = ctx->rel_y = 0;
|
||||
return rect;
|
||||
if (ctx->hovered == ctx->active && ctx->hovered == id) {
|
||||
ctx->hovered = ctx->active = -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->hovered == elem.id && ctx->active == elem.id) {
|
||||
return (rect_t){
|
||||
.topleft.x = ctx->mouse_x + ctx->rel_x,
|
||||
.topleft.y = ctx->mouse_y + ctx->rel_y,
|
||||
.w = rect.w,
|
||||
.h = rect.h,
|
||||
if (ctx->hovered == id && ctx->active == id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aabb(rect, ctx->mouse_x, ctx->mouse_y)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->hovered = id;
|
||||
|
||||
if (ctx->mouse_down) {
|
||||
ctx->active = id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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 NOODLE_ACTION_NONE;
|
||||
}
|
||||
|
||||
u64 id = get_id(ctx);
|
||||
ctx->elements[id] = (ui_elem){
|
||||
.id = id,
|
||||
.ln = ln,
|
||||
.type = UI_ELEM_NOODLE,
|
||||
};
|
||||
|
||||
bool horizontal = ln.p0.y == ln.p1.y;
|
||||
|
||||
rect bounding_box = (rect){0};
|
||||
|
||||
if (horizontal) {
|
||||
i32 x = min(ln.p0.x, ln.p1.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(&ln);
|
||||
|
||||
quad qd = (quad){0};
|
||||
|
||||
if (direction.x == 0) {
|
||||
qd = (quad){
|
||||
.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;
|
||||
|
||||
f32 perpendicular_dy =
|
||||
sqrtf(square(NOODLE_HALF_WIDTH) / (square((f32)slope) + 1.0f));
|
||||
f32 perpendicular_dx = -1.0f * slope * perpendicular_dy;
|
||||
|
||||
qd = (quad){
|
||||
.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},
|
||||
};
|
||||
}
|
||||
|
||||
fill_quad(wnd, qd, colours.fill);
|
||||
|
||||
i32 _min_x_1 = min(qd.p0.x, qd.p1.x);
|
||||
i32 _min_x_2 = min(qd.p2.x, qd.p3.x);
|
||||
i32 min_x = min(_min_x_1, _min_x_2);
|
||||
|
||||
i32 _max_x_1 = max(qd.p0.x, qd.p1.x);
|
||||
i32 _max_x_2 = max(qd.p2.x, qd.p3.x);
|
||||
i32 max_x = max(_max_x_1, _max_x_2);
|
||||
|
||||
i32 _min_y_1 = min(qd.p0.y, qd.p1.y);
|
||||
i32 _min_y_2 = min(qd.p2.y, qd.p3.y);
|
||||
i32 min_y = min(_min_y_1, _min_y_2);
|
||||
|
||||
i32 _max_y_1 = max(qd.p0.y, qd.p1.y);
|
||||
i32 _max_y_2 = max(qd.p2.y, qd.p3.y);
|
||||
i32 max_y = max(_max_y_1, _max_y_2);
|
||||
|
||||
bounding_box = (rect){
|
||||
.topleft.x = min_x,
|
||||
.topleft.y = min_y,
|
||||
.w = max_x - min_x,
|
||||
.h = max_y - min_y,
|
||||
};
|
||||
}
|
||||
|
||||
if (!aabb(&elem, ctx->mouse_x, ctx->mouse_y)) {
|
||||
return rect;
|
||||
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
|
||||
return NOODLE_ACTION_NONE;
|
||||
}
|
||||
|
||||
ctx->hovered = elem.id;
|
||||
if (ctx->mouse_up) {
|
||||
if (ctx->hovered == ctx->active && ctx->hovered == id) {
|
||||
ctx->hovered = ctx->active = -1;
|
||||
return NOODLE_ACTION_RELEASED;
|
||||
}
|
||||
|
||||
return NOODLE_ACTION_NONE;
|
||||
}
|
||||
|
||||
if (ctx->hovered == id && ctx->active == id) {
|
||||
return NOODLE_ACTION_DRAGGING;
|
||||
}
|
||||
|
||||
if (!aabb(bounding_box, ctx->mouse_x, ctx->mouse_y) ||
|
||||
aabb(parent_node, ctx->mouse_x, ctx->mouse_y)) {
|
||||
return NOODLE_ACTION_NONE;
|
||||
}
|
||||
|
||||
ctx->hovered = id;
|
||||
|
||||
if (ctx->mouse_down) {
|
||||
ctx->active = elem.id;
|
||||
ctx->rel_x = rect.topleft.x - ctx->mouse_x;
|
||||
ctx->rel_y = rect.topleft.y - ctx->mouse_y;
|
||||
ctx->active = id;
|
||||
}
|
||||
|
||||
return rect;
|
||||
return NOODLE_ACTION_NONE;
|
||||
}
|
||||
|
||||
internal u64 get_id(ui_ctx *ctx) {
|
||||
// This will always keep the 0 slot empty
|
||||
return ++(ctx->count);
|
||||
}
|
||||
|
145
src/window.c
145
src/window.c
@@ -1,11 +1,14 @@
|
||||
#include "window.h"
|
||||
#include "aliases/aliases.h"
|
||||
#include "aliases.h"
|
||||
#include "math_utils.h"
|
||||
#include <SDL2/SDL_rect.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_video.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool init_window(window_t *wnd, const char *title, u32 width, u32 height, i32 x,
|
||||
internal inline bool inside_triangle(triangle tri, point p);
|
||||
|
||||
bool init_window(window *wnd, const char *title, u32 width, u32 height, i32 x,
|
||||
i32 y) {
|
||||
i32 pos_x = x >= 0 ? x : SDL_WINDOWPOS_CENTERED;
|
||||
i32 pos_y = y >= 0 ? y : SDL_WINDOWPOS_CENTERED;
|
||||
@@ -26,24 +29,24 @@ bool init_window(window_t *wnd, const char *title, u32 width, u32 height, i32 x,
|
||||
wnd->id = SDL_GetWindowID(wnd->window);
|
||||
wnd->title = title;
|
||||
|
||||
i32 x_tmp = -1;
|
||||
i32 y_tmp = -1;
|
||||
SDL_GetWindowPosition(wnd->window, &x_tmp, &y_tmp);
|
||||
i32 xmp = -1;
|
||||
i32 ymp = -1;
|
||||
SDL_GetWindowPosition(wnd->window, &xmp, &ymp);
|
||||
|
||||
wnd->x = x_tmp;
|
||||
wnd->y = y_tmp;
|
||||
wnd->x = xmp;
|
||||
wnd->y = ymp;
|
||||
|
||||
i32 w_tmp = -1;
|
||||
i32 h_tmp = -1;
|
||||
SDL_GetWindowSize(wnd->window, &w_tmp, &h_tmp);
|
||||
i32 wmp = -1;
|
||||
i32 hmp = -1;
|
||||
SDL_GetWindowSize(wnd->window, &wmp, &hmp);
|
||||
|
||||
wnd->width = w_tmp;
|
||||
wnd->height = h_tmp;
|
||||
wnd->width = wmp;
|
||||
wnd->height = hmp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup_window(window_t *wnd) {
|
||||
void cleanup_window(window *wnd) {
|
||||
if (wnd->renderer) {
|
||||
SDL_DestroyRenderer(wnd->renderer);
|
||||
wnd->renderer = NULL;
|
||||
@@ -57,51 +60,139 @@ void cleanup_window(window_t *wnd) {
|
||||
wnd->width = wnd->height = wnd->id = 0;
|
||||
}
|
||||
|
||||
void set_colour(const window_t *wnd, colour_t colour) {
|
||||
void set_colour(const window *wnd, colour colour) {
|
||||
SDL_SetRenderDrawColor(wnd->renderer, colour.colour.r, colour.colour.g,
|
||||
colour.colour.b, colour.colour.a);
|
||||
}
|
||||
|
||||
void clear_window(const window_t *wnd, colour_t colour) {
|
||||
void clear_window(const window *wnd, colour colour) {
|
||||
set_colour(wnd, colour);
|
||||
SDL_RenderClear(wnd->renderer);
|
||||
}
|
||||
|
||||
void swap_buffers(const window_t *wnd) { SDL_RenderPresent(wnd->renderer); }
|
||||
void swap_buffers(const window *wnd) { SDL_RenderPresent(wnd->renderer); }
|
||||
|
||||
void draw_point(const window_t *wnd, point_t p, colour_t colour) {
|
||||
vec2 line_direction(const line *ln) {
|
||||
return (vec2){
|
||||
.x = ln->p1.x - ln->p0.x,
|
||||
.y = ln->p1.y - ln->p0.y,
|
||||
};
|
||||
}
|
||||
|
||||
void draw_point(const window *wnd, point p, colour colour) {
|
||||
set_colour(wnd, colour);
|
||||
SDL_RenderDrawPoint(wnd->renderer, p.x, p.y);
|
||||
}
|
||||
|
||||
void draw_line(const window_t *wnd, const line_t *ln, colour_t colour) {
|
||||
void draw_line(const window *wnd, const line *ln, colour colour) {
|
||||
set_colour(wnd, colour);
|
||||
SDL_RenderDrawLine(wnd->renderer, ln->p0.x, ln->p0.y, ln->p1.x, ln->p1.y);
|
||||
}
|
||||
|
||||
void draw_triangle(const window_t *wnd, const triangle_t *triangle,
|
||||
colour_t colour) {
|
||||
line_t ln0 = {triangle->p0, triangle->p1};
|
||||
line_t ln1 = {triangle->p0, triangle->p2};
|
||||
line_t ln2 = {triangle->p1, triangle->p2};
|
||||
void draw_triangle(const window *wnd, triangle triangle, colour colour) {
|
||||
line ln0 = {triangle.p0, triangle.p1};
|
||||
line ln1 = {triangle.p0, triangle.p2};
|
||||
line ln2 = {triangle.p1, triangle.p2};
|
||||
|
||||
draw_line(wnd, &ln0, colour);
|
||||
draw_line(wnd, &ln1, colour);
|
||||
draw_line(wnd, &ln2, colour);
|
||||
}
|
||||
|
||||
void draw_rect(const window_t *wnd, rect_t rect, colour_t colour) {
|
||||
void draw_rect(const window *wnd, rect rec, colour colour) {
|
||||
set_colour(wnd, colour);
|
||||
|
||||
SDL_Rect dst = {rect.topleft.x, rect.topleft.y, rect.w, rect.h};
|
||||
SDL_Rect dst = {rec.topleft.x, rec.topleft.y, rec.w, rec.h};
|
||||
|
||||
SDL_RenderDrawRect(wnd->renderer, &dst);
|
||||
}
|
||||
|
||||
void fill_rect(const window_t *wnd, rect_t rect, colour_t colour) {
|
||||
void draw_quad(const window *wnd, quad qd, colour colour) {
|
||||
line l0 = (line){qd.p0, qd.p1};
|
||||
line l1 = (line){qd.p1, qd.p3};
|
||||
line l2 = (line){qd.p3, qd.p2};
|
||||
line l3 = (line){qd.p2, qd.p0};
|
||||
|
||||
draw_line(wnd, &l0, colour);
|
||||
draw_line(wnd, &l1, colour);
|
||||
draw_line(wnd, &l2, colour);
|
||||
draw_line(wnd, &l3, colour);
|
||||
}
|
||||
|
||||
void fill_triangle(const window *wnd, triangle tri, colour colour) {
|
||||
// Basic triangle filling algorithm inspired by
|
||||
// https://web.archive.org/web/20050408192410/http://sw-shader.sourceforge.net/rasterizer.html
|
||||
// but uses barycentric coordinates instead of half space
|
||||
i32 x1 = tri.p0.x;
|
||||
i32 x2 = tri.p1.x;
|
||||
i32 x3 = tri.p2.x;
|
||||
|
||||
i32 y1 = tri.p0.y;
|
||||
i32 y2 = tri.p1.y;
|
||||
i32 y3 = tri.p2.y;
|
||||
|
||||
// Find bounding rect
|
||||
i32 min_x = min(min(x1, x2), x3);
|
||||
i32 max_x = max(max(x1, x2), x3);
|
||||
i32 min_y = min(min(y1, y2), y3);
|
||||
i32 max_y = max(max(y1, y2), y3);
|
||||
|
||||
for (i32 y = min_y; y < max_y; ++y) {
|
||||
for (i32 x = min_x; x < max_x; ++x) {
|
||||
if (inside_triangle(tri, (point){x, y})) {
|
||||
draw_point(wnd, (point){x, y}, colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fill_rect(const window *wnd, rect rec, colour colour) {
|
||||
set_colour(wnd, colour);
|
||||
|
||||
SDL_Rect dst = {rect.topleft.x, rect.topleft.y, rect.w, rect.h};
|
||||
SDL_Rect dst = {rec.topleft.x, rec.topleft.y, rec.w, rec.h};
|
||||
|
||||
SDL_RenderFillRect(wnd->renderer, &dst);
|
||||
}
|
||||
|
||||
void fill_quad(const window *wnd, quad qd, colour colour) {
|
||||
triangle t0 = (triangle){qd.p0, qd.p1, qd.p2};
|
||||
triangle t1 = (triangle){qd.p1, qd.p2, qd.p3};
|
||||
|
||||
fill_triangle(wnd, t0, 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
|
||||
f32 cy_min_ay = tri.p2.y - tri.p0.y;
|
||||
f32 cx_min_ax = tri.p2.x - tri.p0.x;
|
||||
f32 by_min_ay = tri.p1.y - tri.p0.y;
|
||||
f32 bx_min_ax = tri.p1.x - tri.p0.x;
|
||||
|
||||
f32 w1 =
|
||||
(tri.p0.x * cy_min_ay + (p.y - tri.p0.y) * cx_min_ax - p.x * cy_min_ay) /
|
||||
(by_min_ay * cx_min_ax - bx_min_ax * cy_min_ay);
|
||||
|
||||
f32 w2 = (p.y - tri.p0.y - w1 * by_min_ay) / cy_min_ay;
|
||||
|
||||
return w1 >= 0.0f && w2 >= 0.0f && (w1 + w2) <= 1.0f;
|
||||
}
|
||||
|
Reference in New Issue
Block a user