Compare commits
	
		
			57 Commits
		
	
	
		
			dacc3be970
			...
			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 | |||
| 60d236c080 | |||
| 571e734ebe | |||
| 680f1ec380 | |||
| f541e3afc3 | |||
| 0ac799cec8 | |||
| 9d438d7347 | |||
| 6d7de03ae8 | |||
| f7449d8014 | |||
| c831fd23f7 | |||
| d114cfce99 | |||
| 9806a5c708 | |||
| 81fbff96b8 | |||
| 10ff46cfe4 | |||
| fc0e3524fe | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
.cache
 | 
					.cache
 | 
				
			||||||
compile_commands.json
 | 
					compile_commands.json
 | 
				
			||||||
main
 | 
					main
 | 
				
			||||||
 | 
					*.dSYM
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,3 @@
 | 
				
			|||||||
[submodule "intern/aliases"]
 | 
					[submodule "intern/wizapp"]
 | 
				
			||||||
	path = intern/aliases
 | 
						path = intern/wizapp
 | 
				
			||||||
	url = https://git.thewizardapprentice.com/abdelrahman/c-cpp-aliases.git
 | 
						url = https://git.thewizardapprentice.com/abdelrahman/wizapp-stdlib.git
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								compile
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								compile
									
									
									
									
									
								
							@@ -1,9 +1,21 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CC=clang
 | 
					CC=clang
 | 
				
			||||||
CFLAGS="-g -Wall -Iinclude -Iintern $(pkg-config --cflags sdl2)"
 | 
					CFLAGS="-g -Wall $(pkg-config --cflags sdl2)"
 | 
				
			||||||
LIBS="$(pkg-config --libs sdl2)"
 | 
					LIBS="$(pkg-config --libs sdl2) -lm"
 | 
				
			||||||
SRC=src/*.c
 | 
					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
 | 
					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
 | 
					#ifndef COMPOSITOR_H
 | 
				
			||||||
#define COMPOSITOR_H
 | 
					#define COMPOSITOR_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "aliases/aliases.h"
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i32 run_main_loop(void);
 | 
					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,35 +1,49 @@
 | 
				
			|||||||
#ifndef NODES_H
 | 
					#ifndef NODES_H
 | 
				
			||||||
#define NODES_H
 | 
					#define NODES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "window.h"
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "ui.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_NODES 1024
 | 
					#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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NODE_WIDTH 70
 | 
					typedef i32 (*node_func)(i32 a, i32 b);
 | 
				
			||||||
#define NODE_HEIGHT 20
 | 
					typedef enum node_type node_type;
 | 
				
			||||||
 | 
					typedef union node_data node_data;
 | 
				
			||||||
 | 
					typedef struct node node;
 | 
				
			||||||
 | 
					typedef struct noodle noodle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IO_NODE_FILL_COLOUR ((colour_t){.abgr = 0xff2c84b7})
 | 
					enum node_type {
 | 
				
			||||||
#define IO_NODE_BORDER_COLOUR ((colour_t){.abgr = 0xff315c89})
 | 
					  NODE_TYPE_IO,
 | 
				
			||||||
#define OP_NODE_FILL_COLOUR ((colour_t){.abgr = 0xffad6c3a})
 | 
					  NODE_TYPE_OP,
 | 
				
			||||||
#define OP_NODE_BORDER_COLOUR ((colour_t){.abgr = 0xff8e4a33})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct node node_t;
 | 
					  COUNT_NODE_TYPES,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum comp_ops {
 | 
					union node_data {
 | 
				
			||||||
  COMP_OP_ADD,
 | 
					  const char *path;
 | 
				
			||||||
  COMP_OP_SUB,
 | 
					  node_func func;
 | 
				
			||||||
  COMP_OP_MUL,
 | 
					};
 | 
				
			||||||
  COMP_OP_DIV,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  COUNT_COMP_OPS,
 | 
					struct noodle {
 | 
				
			||||||
 | 
					  line ln;
 | 
				
			||||||
 | 
					  u64 connected_node;
 | 
				
			||||||
 | 
					  u64 connection_idx;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct node {
 | 
					struct node {
 | 
				
			||||||
  rect_t rect;
 | 
					  rect rec;
 | 
				
			||||||
  const char *path;
 | 
					  ui_elem_colours colours;
 | 
				
			||||||
 | 
					  node_type type;
 | 
				
			||||||
 | 
					  node_data data;
 | 
				
			||||||
 | 
					  u64 inputs;
 | 
				
			||||||
 | 
					  u64 connected;
 | 
				
			||||||
 | 
					  noodle *noodles;
 | 
				
			||||||
 | 
					  noodle **connected_noodles;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool aabb(const node_t *node, i32 x, i32 y);
 | 
					 | 
				
			||||||
void draw_node(const window_t *wnd, const node_t *node);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // !NODES_H
 | 
					#endif // !NODES_H
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								include/ops.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								include/ops.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					#ifndef COMP_OPS_H
 | 
				
			||||||
 | 
					#define COMP_OPS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "nodes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum comp_ops {
 | 
				
			||||||
 | 
					  COMP_OP_ADD,
 | 
				
			||||||
 | 
					  COMP_OP_SUB,
 | 
				
			||||||
 | 
					  COMP_OP_MUL,
 | 
				
			||||||
 | 
					  COMP_OP_DIV,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  COUNT_COMP_OPS,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i32 comp_add(i32 a, i32 b);
 | 
				
			||||||
 | 
					i32 comp_sub(i32 a, i32 b);
 | 
				
			||||||
 | 
					i32 comp_mul(i32 a, i32 b);
 | 
				
			||||||
 | 
					i32 comp_div(i32 a, i32 b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal node_func ops[COUNT_COMP_OPS] = {
 | 
				
			||||||
 | 
					    [COMP_OP_ADD] = comp_add,
 | 
				
			||||||
 | 
					    [COMP_OP_SUB] = comp_sub,
 | 
				
			||||||
 | 
					    [COMP_OP_MUL] = comp_mul,
 | 
				
			||||||
 | 
					    [COMP_OP_DIV] = comp_div,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // !COMP_OPS_H
 | 
				
			||||||
							
								
								
									
										77
									
								
								include/ui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								include/ui.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					#ifndef UI_H
 | 
				
			||||||
 | 
					#define UI_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "SDL_events.h"
 | 
				
			||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "window.h"
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_UI_ELEMENTS 8192
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BUTTON_WIDTH 100
 | 
				
			||||||
 | 
					#define BUTTON_HEIGHT 40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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,
 | 
				
			||||||
 | 
					  UI_ELEM_NOODLE,
 | 
				
			||||||
 | 
					  UI_ELEM_BUTTON,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  COUNT_UI_ELEM,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ui_elem {
 | 
				
			||||||
 | 
					  u64 id;
 | 
				
			||||||
 | 
					  union {
 | 
				
			||||||
 | 
					    rect rec;
 | 
				
			||||||
 | 
					    line ln;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ui_elem_type type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ui_elem_colours {
 | 
				
			||||||
 | 
					  colour fill;
 | 
				
			||||||
 | 
					  colour border;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum noodle_action {
 | 
				
			||||||
 | 
					  NOODLE_ACTION_NONE,
 | 
				
			||||||
 | 
					  NOODLE_ACTION_DRAGGING,
 | 
				
			||||||
 | 
					  NOODLE_ACTION_RELEASED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ui_ctx {
 | 
				
			||||||
 | 
					  u64 count;
 | 
				
			||||||
 | 
					  i64 hovered;
 | 
				
			||||||
 | 
					  i64 active;
 | 
				
			||||||
 | 
					  i32 mouse_x;
 | 
				
			||||||
 | 
					  i32 mouse_y;
 | 
				
			||||||
 | 
					  i32 rel_x;
 | 
				
			||||||
 | 
					  i32 rel_y;
 | 
				
			||||||
 | 
					  bool mouse_down;
 | 
				
			||||||
 | 
					  bool mouse_up;
 | 
				
			||||||
 | 
					  const window *wnd;
 | 
				
			||||||
 | 
					  ui_elem elements[MAX_UI_ELEMENTS];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
					#ifndef WINDOW_H
 | 
				
			||||||
#define WINDOW_H
 | 
					#define WINDOW_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "aliases/aliases.h"
 | 
					#include "aliases.h"
 | 
				
			||||||
#include <SDL2/SDL_pixels.h>
 | 
					#include <SDL2/SDL_pixels.h>
 | 
				
			||||||
#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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct point point_t;
 | 
					typedef struct point point;
 | 
				
			||||||
typedef struct line line_t;
 | 
					typedef point vec2;
 | 
				
			||||||
typedef struct triangle triangle_t;
 | 
					typedef struct line line;
 | 
				
			||||||
typedef struct rect rect_t;
 | 
					typedef struct triangle triangle;
 | 
				
			||||||
typedef struct window window_t;
 | 
					typedef struct quad quad;
 | 
				
			||||||
 | 
					typedef struct rect rect;
 | 
				
			||||||
 | 
					typedef struct window window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct point {
 | 
					struct point {
 | 
				
			||||||
  i32 x;
 | 
					  i32 x;
 | 
				
			||||||
@@ -19,23 +21,33 @@ struct point {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct line {
 | 
					struct line {
 | 
				
			||||||
  point_t p0;
 | 
					  point p0;
 | 
				
			||||||
  point_t p1;
 | 
					  point p1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct triangle {
 | 
					struct triangle {
 | 
				
			||||||
  point_t p0;
 | 
					  point p0;
 | 
				
			||||||
  point_t p1;
 | 
					  point p1;
 | 
				
			||||||
  point_t p2;
 | 
					  point p2;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct quad {
 | 
				
			||||||
 | 
					  point p0;
 | 
				
			||||||
 | 
					  point p1;
 | 
				
			||||||
 | 
					  point p2;
 | 
				
			||||||
 | 
					  point p3;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct rect {
 | 
					struct rect {
 | 
				
			||||||
  point_t topleft;
 | 
					  point topleft;
 | 
				
			||||||
  i32 w;
 | 
					  i32 w;
 | 
				
			||||||
  i32 h;
 | 
					  i32 h;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct window {
 | 
					struct window {
 | 
				
			||||||
 | 
					  u32 id;
 | 
				
			||||||
 | 
					  u64 x;
 | 
				
			||||||
 | 
					  u64 y;
 | 
				
			||||||
  u64 width;
 | 
					  u64 width;
 | 
				
			||||||
  u64 height;
 | 
					  u64 height;
 | 
				
			||||||
  const char *title;
 | 
					  const char *title;
 | 
				
			||||||
@@ -43,7 +55,7 @@ struct window {
 | 
				
			|||||||
  SDL_Renderer *renderer;
 | 
					  SDL_Renderer *renderer;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct colour colour_t;
 | 
					typedef struct colour colour;
 | 
				
			||||||
struct colour {
 | 
					struct colour {
 | 
				
			||||||
  union {
 | 
					  union {
 | 
				
			||||||
    u32 abgr;
 | 
					    u32 abgr;
 | 
				
			||||||
@@ -51,15 +63,24 @@ struct colour {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool init_window(window_t *wnd, const char *title, u64 width, u64 height);
 | 
					bool init_window(window *wnd, const char *title, u32 width, u32 height, i32 x,
 | 
				
			||||||
void cleanup_window(window_t *wnd);
 | 
					                 i32 y);
 | 
				
			||||||
void clear_window(const window_t *wnd, colour_t colour);
 | 
					void cleanup_window(window *wnd);
 | 
				
			||||||
void swap_buffers(const window_t *wnd);
 | 
					void clear_window(const window *wnd, colour colour);
 | 
				
			||||||
void draw_point(const window_t *wnd, point_t p, colour_t colour);
 | 
					void swap_buffers(const window *wnd);
 | 
				
			||||||
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,
 | 
					vec2 line_direction(const line *ln);
 | 
				
			||||||
                   colour_t colour);
 | 
					
 | 
				
			||||||
void draw_rect(const window_t *wnd, const rect_t *rect, colour_t colour);
 | 
					void draw_point(const window *wnd, point p, colour colour);
 | 
				
			||||||
void fill_rect(const window_t *wnd, const rect_t *rect, colour_t 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
 | 
					#endif // !WINDOW_H
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule intern/aliases deleted from f95f3aa499
									
								
							
							
								
								
									
										1
									
								
								intern/wizapp
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								intern/wizapp
									
									
									
									
									
										Submodule
									
								
							 Submodule intern/wizapp added at 7948d3fd1a
									
								
							
							
								
								
									
										367
									
								
								src/compositor.c
									
									
									
									
									
								
							
							
						
						
									
										367
									
								
								src/compositor.c
									
									
									
									
									
								
							@@ -1,5 +1,8 @@
 | 
				
			|||||||
#include "aliases/aliases.h"
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "mem_arena.h"
 | 
				
			||||||
#include "nodes.h"
 | 
					#include "nodes.h"
 | 
				
			||||||
 | 
					#include "ops.h"
 | 
				
			||||||
 | 
					#include "ui.h"
 | 
				
			||||||
#include "window.h"
 | 
					#include "window.h"
 | 
				
			||||||
#include <SDL2/SDL.h>
 | 
					#include <SDL2/SDL.h>
 | 
				
			||||||
#include <SDL2/SDL_events.h>
 | 
					#include <SDL2/SDL_events.h>
 | 
				
			||||||
@@ -13,119 +16,357 @@
 | 
				
			|||||||
#define WINDOW_WIDTH 1280
 | 
					#define WINDOW_WIDTH 1280
 | 
				
			||||||
#define WINDOW_HEIGHT 720
 | 
					#define WINDOW_HEIGHT 720
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct compositor compositor_t;
 | 
					#define ARENA_CAPACITY 1 * 1024 * 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct compositor compositor;
 | 
				
			||||||
struct compositor {
 | 
					struct compositor {
 | 
				
			||||||
  window_t windows[MAX_WINDOWS];
 | 
					  Arena *arena;
 | 
				
			||||||
 | 
					  window windows[MAX_WINDOWS];
 | 
				
			||||||
 | 
					  u32 active_window;
 | 
				
			||||||
  SDL_Event event;
 | 
					  SDL_Event event;
 | 
				
			||||||
  bool running;
 | 
					  bool running;
 | 
				
			||||||
  u64 mouse_x;
 | 
					 | 
				
			||||||
  u64 mouse_y;
 | 
					 | 
				
			||||||
  i64 node_hovered;
 | 
					 | 
				
			||||||
  u64 count;
 | 
					  u64 count;
 | 
				
			||||||
  node_t *nodes;
 | 
					  node *nodes;
 | 
				
			||||||
  bool move_node;
 | 
					  node *back_nodes;
 | 
				
			||||||
 | 
					  ui_ctx ctx;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void add_node(compositor_t *comp, const char *path, i32 x, i32 y);
 | 
					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) {
 | 
					i32 run_main_loop(void) {
 | 
				
			||||||
  if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
 | 
					  if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
 | 
				
			||||||
    return EXIT_FAILURE;
 | 
					    return EXIT_FAILURE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  compositor_t comp = {0};
 | 
					  compositor comp = {0};
 | 
				
			||||||
  comp.nodes = (node_t *)malloc(sizeof(node_t) * MAX_NODES);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  window_t *main_window = &(comp.windows[0]);
 | 
					  init_ui_ctx(&(comp.ctx));
 | 
				
			||||||
 | 
					  mem_arena_init(&comp.arena, ARENA_CAPACITY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!init_window(main_window, "Compositor", WINDOW_WIDTH, WINDOW_HEIGHT)) {
 | 
					  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]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!init_window(main_window, "Compositor", WINDOW_WIDTH, WINDOW_HEIGHT, -1,
 | 
				
			||||||
 | 
					                   -1)) {
 | 
				
			||||||
    SDL_Quit();
 | 
					    SDL_Quit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return EXIT_FAILURE;
 | 
					    return EXIT_FAILURE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  u32 toolbox_window_width = WINDOW_WIDTH / 7;
 | 
				
			||||||
 | 
					  init_window(toolbox, "Toolbox", toolbox_window_width, WINDOW_HEIGHT,
 | 
				
			||||||
 | 
					              main_window->x - toolbox_window_width, -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  comp.running = true;
 | 
					  comp.running = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
 | 
					  SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  colour_t bg_colour = {.abgr = 0xffffffff};
 | 
					  colour bg_colour = {.abgr = 0xffffffff};
 | 
				
			||||||
 | 
					  ui_elem_colours button_colours = (ui_elem_colours){
 | 
				
			||||||
 | 
					      .fill = (colour){.abgr = 0xff89a83c},
 | 
				
			||||||
 | 
					      .border = (colour){.abgr = 0xff768432},
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ui_elem_colours io_node_colours = (ui_elem_colours){
 | 
				
			||||||
 | 
					      .fill = (colour){.abgr = 0xff2c84b7},
 | 
				
			||||||
 | 
					      .border = (colour){.abgr = 0xff315c89},
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (comp.running) {
 | 
					  while (comp.running) {
 | 
				
			||||||
    while (SDL_PollEvent(&(comp.event))) {
 | 
					    while (SDL_PollEvent(&(comp.event))) {
 | 
				
			||||||
      switch (comp.event.type) {
 | 
					      handle_ui_events(&(comp.windows[comp.active_window - 1]), &(comp.ctx),
 | 
				
			||||||
      case SDL_QUIT:
 | 
					                       &(comp.event));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (comp.event.type == SDL_QUIT) {
 | 
				
			||||||
        comp.running = false;
 | 
					        comp.running = false;
 | 
				
			||||||
        break;
 | 
					      }
 | 
				
			||||||
      case SDL_MOUSEBUTTONDOWN:
 | 
					
 | 
				
			||||||
        if (comp.node_hovered != -1) {
 | 
					      if (comp.event.type == SDL_WINDOWEVENT) {
 | 
				
			||||||
          comp.move_node = true;
 | 
					        if (comp.event.window.event == SDL_WINDOWEVENT_CLOSE) {
 | 
				
			||||||
 | 
					          comp.running = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        break;
 | 
					        if (comp.event.window.event == SDL_WINDOWEVENT_ENTER) {
 | 
				
			||||||
      case SDL_MOUSEBUTTONUP:
 | 
					          u32 id = comp.event.window.windowID;
 | 
				
			||||||
        comp.move_node = false;
 | 
					          window *wnd = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        break;
 | 
					          for (u64 i = 0; i < MAX_WINDOWS; ++i) {
 | 
				
			||||||
      case SDL_MOUSEMOTION:
 | 
					            window *window = &(comp.windows[i]);
 | 
				
			||||||
        comp.mouse_x = comp.event.motion.x;
 | 
					 | 
				
			||||||
        comp.mouse_y = comp.event.motion.y;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (comp.move_node) {
 | 
					            if (id == window->id) {
 | 
				
			||||||
          i32 dx = comp.event.motion.xrel;
 | 
					              comp.active_window = id;
 | 
				
			||||||
          i32 dy = comp.event.motion.yrel;
 | 
					              wnd = window;
 | 
				
			||||||
 | 
					 | 
				
			||||||
          node_t *node = &(comp.nodes[comp.node_hovered]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          node->rect.topleft.x += dx;
 | 
					 | 
				
			||||||
          node->rect.topleft.y += dy;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          comp.node_hovered = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          for (u64 i = comp.count - 1; i >= 0; --i) {
 | 
					 | 
				
			||||||
            node_t *node = &(comp.nodes[i]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (aabb(node, comp.mouse_x, comp.mouse_y)) {
 | 
					 | 
				
			||||||
              comp.node_hovered = i;
 | 
					 | 
				
			||||||
              break;
 | 
					              break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        break;
 | 
					          if (wnd) {
 | 
				
			||||||
      case SDL_DROPFILE:
 | 
					            SDL_RaiseWindow(wnd->window);
 | 
				
			||||||
        add_node(&comp, comp.event.drop.file, comp.mouse_x, comp.mouse_y);
 | 
					          }
 | 
				
			||||||
        break;
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clear_window(main_window, bg_colour);
 | 
					    update_node_graph(&comp, main_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (u64 i = 0; i < comp.count; ++i) {
 | 
					    for (u64 i = 0; i < MAX_WINDOWS; ++i) {
 | 
				
			||||||
      node_t *node = &(comp.nodes[i]);
 | 
					      clear_window(&(comp.windows[i]), bg_colour);
 | 
				
			||||||
      draw_node(main_window, node);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    swap_buffers(main_window);
 | 
					    for (u64 i = 0; i < COUNT_COMP_OPS; ++i) {
 | 
				
			||||||
 | 
					      rect rect = {
 | 
				
			||||||
 | 
					          .topleft.x = toolbox_button_x,
 | 
				
			||||||
 | 
					          .topleft.y = i * (BUTTON_HEIGHT + 20) + 30,
 | 
				
			||||||
 | 
					          .w = BUTTON_WIDTH,
 | 
				
			||||||
 | 
					          .h = BUTTON_HEIGHT,
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (ui_button(toolbox, &(comp.ctx), rect, button_colours)) {
 | 
				
			||||||
 | 
					        node_data data = (node_data){.func = ops[i]};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        add_node(&comp, NODE_TYPE_OP, data, OP_INPUT_COUNT, comp.ctx.mouse_x,
 | 
				
			||||||
 | 
					                 comp.ctx.mouse_y, op_node_colours);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    draw_node_graph(&comp, main_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (u64 i = 0; i < MAX_WINDOWS; ++i) {
 | 
				
			||||||
 | 
					      swap_buffers(&(comp.windows[i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reset_ui_ctx(&(comp.ctx));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (u64 i = 0; i < MAX_WINDOWS; ++i) {
 | 
				
			||||||
 | 
					    cleanup_window(&(comp.windows[i]));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SDL_Quit();
 | 
					  SDL_Quit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mem_arena_free(&comp.arena);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return EXIT_SUCCESS;
 | 
					  return EXIT_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void add_node(compositor_t *comp, const char *path, i32 x, i32 y) {
 | 
					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) {
 | 
					  if (comp->count + 1 >= MAX_NODES) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  comp->nodes[(comp->count)++] = (node_t){
 | 
					  u64 alloc_size = inputs * sizeof(noodle);
 | 
				
			||||||
      .rect =
 | 
					  noodle *noodles = mem_arena_alloc(comp->arena, alloc_size);
 | 
				
			||||||
          (rect_t){
 | 
					  noodle *back_noodles = mem_arena_alloc(comp->arena, alloc_size);
 | 
				
			||||||
              .topleft.x = x,
 | 
					  if (!noodles || !back_noodles) {
 | 
				
			||||||
              .topleft.y = y,
 | 
					    return;
 | 
				
			||||||
              .w = NODE_WIDTH,
 | 
					  }
 | 
				
			||||||
              .h = NODE_HEIGHT,
 | 
					
 | 
				
			||||||
          },
 | 
					  u64 connected_alloc_size = MAX_NODES * sizeof(noodle *);
 | 
				
			||||||
      .path = path,
 | 
					  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"
 | 
					#include "compositor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i32 main(void) { return run_main_loop(); }
 | 
					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; }
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/nodes.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/nodes.c
									
									
									
									
									
								
							@@ -1,13 +0,0 @@
 | 
				
			|||||||
#include "nodes.h"
 | 
					 | 
				
			||||||
#include "aliases/aliases.h"
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool aabb(const node_t *node, i32 x, i32 y) {
 | 
					 | 
				
			||||||
  return x > node->rect.topleft.x && x <= node->rect.topleft.x + node->rect.w &&
 | 
					 | 
				
			||||||
         y > node->rect.topleft.y && y <= node->rect.topleft.y + node->rect.h;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void draw_node(const window_t *wnd, const node_t *node) {
 | 
					 | 
				
			||||||
  fill_rect(wnd, &(node->rect), IO_NODE_FILL_COLOUR);
 | 
					 | 
				
			||||||
  draw_rect(wnd, &(node->rect), IO_NODE_BORDER_COLOUR);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										10
									
								
								src/ops.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/ops.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					#include "ops.h"
 | 
				
			||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i32 comp_add(i32 a, i32 b) { return a + b; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i32 comp_sub(i32 a, i32 b) { return a - b; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i32 comp_mul(i32 a, i32 b) { return a * b; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i32 comp_div(i32 a, i32 b) { return a / b; }
 | 
				
			||||||
							
								
								
									
										253
									
								
								src/ui.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								src/ui.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,253 @@
 | 
				
			|||||||
 | 
					#include "ui.h"
 | 
				
			||||||
 | 
					#include "SDL_events.h"
 | 
				
			||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "math_utils.h"
 | 
				
			||||||
 | 
					#include "window.h"
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NOODLE_HALF_WIDTH 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 *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 *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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ui_button(const window *wnd, ui_ctx *ctx, rect rec,
 | 
				
			||||||
 | 
					               ui_elem_colours colours) {
 | 
				
			||||||
 | 
					  if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  u64 id = get_id(ctx);
 | 
				
			||||||
 | 
					  ctx->elements[id] = (ui_elem){
 | 
				
			||||||
 | 
					      .id = id,
 | 
				
			||||||
 | 
					      .rec = rec,
 | 
				
			||||||
 | 
					      .type = UI_ELEM_BUTTON,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fill_rect(wnd, rec, colours.fill);
 | 
				
			||||||
 | 
					  draw_rect(wnd, rec, colours.border);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!aabb(rec, ctx->mouse_x, ctx->mouse_y)) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ctx->hovered = id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ctx->mouse_down) {
 | 
				
			||||||
 | 
					    ctx->active = id;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ctx->mouse_up && ctx->hovered == id && ctx->active == id) {
 | 
				
			||||||
 | 
					    ctx->hovered = ctx->active = -1;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ui_node(const window *wnd, ui_ctx *ctx, rect rect,
 | 
				
			||||||
 | 
					             ui_elem_colours colours) {
 | 
				
			||||||
 | 
					  if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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 != id)) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ctx->mouse_up) {
 | 
				
			||||||
 | 
					    if (ctx->hovered == ctx->active && ctx->hovered == id) {
 | 
				
			||||||
 | 
					      ctx->hovered = ctx->active = -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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 (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != id)) {
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 = id;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return NOODLE_ACTION_NONE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal u64 get_id(ui_ctx *ctx) {
 | 
				
			||||||
 | 
					  // This will always keep the 0 slot empty
 | 
				
			||||||
 | 
					  return ++(ctx->count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										151
									
								
								src/window.c
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								src/window.c
									
									
									
									
									
								
							@@ -1,14 +1,20 @@
 | 
				
			|||||||
#include "window.h"
 | 
					#include "window.h"
 | 
				
			||||||
#include "aliases/aliases.h"
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "math_utils.h"
 | 
				
			||||||
#include <SDL2/SDL_rect.h>
 | 
					#include <SDL2/SDL_rect.h>
 | 
				
			||||||
#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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool init_window(window_t *wnd, const char *title, u64 width, u64 height) {
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wnd->window =
 | 
					  wnd->window =
 | 
				
			||||||
      SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 | 
					      SDL_CreateWindow(title, pos_x, pos_y, width, height, SDL_WINDOW_SHOWN);
 | 
				
			||||||
                       width, height, SDL_WINDOW_SHOWN);
 | 
					 | 
				
			||||||
  if (!(wnd->window)) {
 | 
					  if (!(wnd->window)) {
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -20,14 +26,27 @@ bool init_window(window_t *wnd, const char *title, u64 width, u64 height) {
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wnd->id = SDL_GetWindowID(wnd->window);
 | 
				
			||||||
  wnd->title = title;
 | 
					  wnd->title = title;
 | 
				
			||||||
  wnd->width = width;
 | 
					
 | 
				
			||||||
  wnd->height = height;
 | 
					  i32 xmp = -1;
 | 
				
			||||||
 | 
					  i32 ymp = -1;
 | 
				
			||||||
 | 
					  SDL_GetWindowPosition(wnd->window, &xmp, &ymp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wnd->x = xmp;
 | 
				
			||||||
 | 
					  wnd->y = ymp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  i32 wmp = -1;
 | 
				
			||||||
 | 
					  i32 hmp = -1;
 | 
				
			||||||
 | 
					  SDL_GetWindowSize(wnd->window, &wmp, &hmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wnd->width = wmp;
 | 
				
			||||||
 | 
					  wnd->height = hmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cleanup_window(window_t *wnd) {
 | 
					void cleanup_window(window *wnd) {
 | 
				
			||||||
  if (wnd->renderer) {
 | 
					  if (wnd->renderer) {
 | 
				
			||||||
    SDL_DestroyRenderer(wnd->renderer);
 | 
					    SDL_DestroyRenderer(wnd->renderer);
 | 
				
			||||||
    wnd->renderer = NULL;
 | 
					    wnd->renderer = NULL;
 | 
				
			||||||
@@ -38,54 +57,142 @@ void cleanup_window(window_t *wnd) {
 | 
				
			|||||||
    wnd->window = NULL;
 | 
					    wnd->window = NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wnd->width = wnd->height = 0;
 | 
					  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,
 | 
					  SDL_SetRenderDrawColor(wnd->renderer, colour.colour.r, colour.colour.g,
 | 
				
			||||||
                         colour.colour.b, colour.colour.a);
 | 
					                         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);
 | 
					  set_colour(wnd, colour);
 | 
				
			||||||
  SDL_RenderClear(wnd->renderer);
 | 
					  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);
 | 
					  set_colour(wnd, colour);
 | 
				
			||||||
  SDL_RenderDrawPoint(wnd->renderer, p.x, p.y);
 | 
					  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);
 | 
					  set_colour(wnd, colour);
 | 
				
			||||||
  SDL_RenderDrawLine(wnd->renderer, ln->p0.x, ln->p0.y, ln->p1.x, ln->p1.y);
 | 
					  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,
 | 
					void draw_triangle(const window *wnd, triangle triangle, colour colour) {
 | 
				
			||||||
                   colour_t colour) {
 | 
					  line ln0 = {triangle.p0, triangle.p1};
 | 
				
			||||||
  line_t ln0 = {triangle->p0, triangle->p1};
 | 
					  line ln1 = {triangle.p0, triangle.p2};
 | 
				
			||||||
  line_t ln1 = {triangle->p0, triangle->p2};
 | 
					  line ln2 = {triangle.p1, triangle.p2};
 | 
				
			||||||
  line_t ln2 = {triangle->p1, triangle->p2};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  draw_line(wnd, &ln0, colour);
 | 
					  draw_line(wnd, &ln0, colour);
 | 
				
			||||||
  draw_line(wnd, &ln1, colour);
 | 
					  draw_line(wnd, &ln1, colour);
 | 
				
			||||||
  draw_line(wnd, &ln2, colour);
 | 
					  draw_line(wnd, &ln2, colour);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void draw_rect(const window_t *wnd, const rect_t *rect, colour_t colour) {
 | 
					void draw_rect(const window *wnd, rect rec, colour colour) {
 | 
				
			||||||
  set_colour(wnd, 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);
 | 
					  SDL_RenderDrawRect(wnd->renderer, &dst);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void fill_rect(const window_t *wnd, const 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);
 | 
					  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);
 | 
					  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