Compare commits

...

2 Commits

Author SHA1 Message Date
Beriff
ed9aca01e4 feat(untested): add handles base 2026-03-11 14:19:05 +07:00
Beriff
6c8ca19fbf feat: add circle tool 2026-03-11 09:46:30 +07:00
8 changed files with 321 additions and 78 deletions

View File

@@ -90,9 +90,6 @@ static void canvas_onclick(GtkGestureClick* gesture, int n_press, double x,
int widget_w = gtk_widget_get_width(widget); int widget_w = gtk_widget_get_width(widget);
int widget_h = gtk_widget_get_height(widget); int widget_h = gtk_widget_get_height(widget);
int canvas_w = state->canvas->width;
int canvas_h = state->canvas->height;
V2 normalized_coords = V2 normalized_coords =
(V2){(2 * (x / widget_w)) - 1, 1 - (2 * (y / widget_h))}; (V2){(2 * (x / widget_w)) - 1, 1 - (2 * (y / widget_h))};
@@ -157,6 +154,25 @@ begin_click_dispatch:
} }
vektor_polygon_add_point(state->selectedShape->primitive.polygon, pos); vektor_polygon_add_point(state->selectedShape->primitive.polygon, pos);
vektor_shapes_update_bbox(state->shapeBuffer);
} else if (state->selectedTool == VektorCircleTool) {
VektorCircle* circle = vektor_circle_new();
VektorPrimitive circlePrimitive =
(VektorPrimitive){.kind = VEKTOR_CIRCLE, .circle = *circle};
VektorStyle style = (VektorStyle){.stroke_color = state->currentColor,
.stroke_width = 0.01};
vektor_shapebuffer_add_shape(
state->shapeBuffer, vektor_shape_new(circlePrimitive, style, 0));
state->selectedShape =
&(state->shapeBuffer->shapes[state->shapeBuffer->count - 1]);
vektor_circle_free(circle);
vektor_circle_set_center(&state->selectedShape->primitive.circle, pos);
vektor_circle_set_radius(&state->selectedShape->primitive.circle, 0.1f);
vektor_shapes_update_bbox(state->shapeBuffer); vektor_shapes_update_bbox(state->shapeBuffer);
} else if (state->selectedTool == VektorRectangleTool) { } else if (state->selectedTool == VektorRectangleTool) {
@@ -185,7 +201,6 @@ begin_click_dispatch:
state->shapeBuffer->shapes[i].primitive); state->shapeBuffer->shapes[i].primitive);
if (vektor_bbox_isinside(bbox, pos)) { if (vektor_bbox_isinside(bbox, pos)) {
state->selectedShape = &(state->shapeBuffer->shapes[i]); state->selectedShape = &(state->shapeBuffer->shapes[i]);
g_print("%d", state->selectedShape == NULL);
return; return;
} }
} }
@@ -194,6 +209,36 @@ begin_click_dispatch:
} }
} }
void vektor_appstate_canvas_drag_begin(GtkGestureDrag* gesture, gdouble x,
gdouble y, gpointer user_data) {
GtkWidget* widget =
gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
int widget_w = gtk_widget_get_width(widget);
int widget_h = gtk_widget_get_height(widget);
V2 normalized_coords =
(V2){(2 * (x / widget_w)) - 1, 1 - (2 * (y / widget_h))};
}
void vektor_appstate_canvas_drag_update(GtkGestureDrag* gesture,
gdouble x, gdouble y,
gpointer user_data) {
gdouble start_x, start_y;
gtk_gesture_drag_get_start_point(gesture, &start_x, &start_y);
GtkWidget* widget =
gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
int widget_w = gtk_widget_get_width(widget);
int widget_h = gtk_widget_get_height(widget);
V2 norm =
(V2){(2 * ( (x+start_x) / widget_w)) - 1, 1 - (2 * ( (y+start_y) / widget_h))};
}
void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) { void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
button_tool_set_data* data_linetool = malloc(sizeof(button_tool_set_data)); button_tool_set_data* data_linetool = malloc(sizeof(button_tool_set_data));
data_linetool->state = stateOut; data_linetool->state = stateOut;
@@ -217,22 +262,21 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
data_selecttool->state = stateOut; data_selecttool->state = stateOut;
data_selecttool->tool = VektorSelectionTool; data_selecttool->tool = VektorSelectionTool;
button_tool_set_data* data_circletool =
malloc(sizeof(button_tool_set_data));
data_circletool->state = stateOut;
data_circletool->tool = VektorCircleTool;
data_circletool->revealer = wstate->workspaceRevealerShapes;
// populate appstate // populate appstate
stateOut->startupTime = g_get_monotonic_time(); stateOut->startupTime = g_get_monotonic_time();
stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer)); stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer));
*stateOut->shapeBuffer = (VektorShapeBuffer){0}; *stateOut->shapeBuffer = (VektorShapeBuffer){0};
VektorCircle circ = (VektorCircle){.center = (V2){0, 0}, .radius = 0.3};
VektorShape shp = vektor_shape_new(
(VektorPrimitive){.kind = VEKTOR_CIRCLE, .circle = circ},
(VektorStyle){.stroke_color = stateOut->currentColor, 0.01}, 0);
vektor_shapebuffer_add_shape(stateOut->shapeBuffer, shp);
stateOut->canvas = malloc(sizeof(VektorCanvas)); stateOut->canvas = malloc(sizeof(VektorCanvas));
stateOut->widgetState = wstate; stateOut->widgetState = wstate;
stateOut->currentColor = vektor_color_solid(0, 0, 0); stateOut->currentColor = vektor_color_solid(0, 0, 0);
stateOut->selectedShape = NULL; stateOut->selectedShape = NULL;
VektorCanvasRenderInfo* renderInfo = malloc(sizeof(VektorCanvasRenderInfo)); VektorCanvasRenderInfo* renderInfo = malloc(sizeof(VektorCanvasRenderInfo));
renderInfo->zoom = 1; renderInfo->zoom = 1;
renderInfo->panX = 0; renderInfo->panX = 0;
@@ -245,13 +289,14 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
renderInfo->canvasMat = m33_identity(); renderInfo->canvasMat = m33_identity();
vektor_canvas_init(wstate, stateOut->canvas, renderInfo); vektor_canvas_init(wstate, stateOut->canvas, renderInfo);
stateOut->renderInfo = renderInfo; stateOut->renderInfo = renderInfo;
// link all the buttons // link all the buttons
g_signal_connect(G_OBJECT(wstate->workspaceButtonLineTool), "clicked", g_signal_connect(G_OBJECT(wstate->workspaceButtonLineTool), "clicked",
G_CALLBACK(appstate_set_tool), data_linetool); G_CALLBACK(appstate_set_tool), data_linetool);
g_signal_connect(G_OBJECT(wstate->workspaceButtonRectTool), "clicked", g_signal_connect(G_OBJECT(wstate->workspaceButtonRectTool), "clicked",
G_CALLBACK(appstate_set_tool), data_rectangletool); G_CALLBACK(appstate_set_tool), data_rectangletool);
g_signal_connect(G_OBJECT(wstate->workspaceButtonCircleTool), "clicked", g_signal_connect(G_OBJECT(wstate->workspaceButtonCircleTool), "clicked",
G_CALLBACK(appstate_set_tool), data_linetool); G_CALLBACK(appstate_set_tool), data_circletool);
g_signal_connect(G_OBJECT(wstate->workspaceButtonPolygonTool), "clicked", g_signal_connect(G_OBJECT(wstate->workspaceButtonPolygonTool), "clicked",
G_CALLBACK(appstate_set_tool), data_polygontool); G_CALLBACK(appstate_set_tool), data_polygontool);
g_signal_connect(G_OBJECT(wstate->workspaceButtonSelectionTool), "clicked", g_signal_connect(G_OBJECT(wstate->workspaceButtonSelectionTool), "clicked",
@@ -283,4 +328,14 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
G_CALLBACK(canvas_onclick), stateOut); G_CALLBACK(canvas_onclick), stateOut);
gtk_widget_add_controller(GTK_WIDGET(wstate->workspaceCanvas), gtk_widget_add_controller(GTK_WIDGET(wstate->workspaceCanvas),
GTK_EVENT_CONTROLLER(canvasClickGesture)); GTK_EVENT_CONTROLLER(canvasClickGesture));
// Add drag gesture to canvas
GtkGesture* canvasDragGesture = gtk_gesture_drag_new();
g_signal_connect(G_OBJECT(canvasDragGesture), "drag-update",
G_CALLBACK(vektor_appstate_canvas_drag_update), stateOut);
g_signal_connect(G_OBJECT(canvasDragGesture), "drag-begin",
G_CALLBACK(vektor_appstate_canvas_drag_begin), stateOut);
gtk_widget_add_controller(GTK_WIDGET(wstate->workspaceCanvas),
GTK_EVENT_CONTROLLER(canvasDragGesture));
} }

View File

@@ -10,7 +10,8 @@ typedef enum VektorAppTool {
VektorSelectionTool, VektorSelectionTool,
VektorLineTool, VektorLineTool,
VektorPolygonTool, VektorPolygonTool,
VektorRectangleTool VektorRectangleTool,
VektorCircleTool
} VektorAppTool; } VektorAppTool;
typedef struct VektorAppState { typedef struct VektorAppState {

View File

@@ -1,8 +1,12 @@
#include "primitives.h" #include "primitives.h"
#include "glib.h"
#include "src/core/vector.h"
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <stddef.h> #include <stddef.h>
// ------ PER-PRIMITIVE METHODS ------
VektorPolyline* vektor_polyline_new(void) { VektorPolyline* vektor_polyline_new(void) {
VektorPolyline* pl = malloc(sizeof(VektorPolyline)); VektorPolyline* pl = malloc(sizeof(VektorPolyline));
pl->count = 0; pl->count = 0;
@@ -74,6 +78,10 @@ void vektor_circle_set_radius(VektorCircle* circle, double radius) {
circle->radius = radius; circle->radius = radius;
} }
void vektor_circle_free(VektorCircle* circle) {
free(circle);
}
VektorRectangle* vektor_rectangle_new(void) { VektorRectangle* vektor_rectangle_new(void) {
VektorRectangle* rct = malloc(sizeof(VektorRectangle)); VektorRectangle* rct = malloc(sizeof(VektorRectangle));
rct->start = (V2){.x = 0, .y = 0}; rct->start = (V2){.x = 0, .y = 0};
@@ -90,32 +98,24 @@ void vektor_rectangle_set_start(VektorRectangle* rct, V2 point) {
void vektor_rectangle_free(VektorRectangle* rct) { free(rct); } void vektor_rectangle_free(VektorRectangle* rct) { free(rct); }
void vektor_shapebuffer_add_shape(VektorShapeBuffer* buffer,
VektorShape shape) {
if (buffer->count >= buffer->capacity) {
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
buffer->shapes =
realloc(buffer->shapes, sizeof(VektorShape) * buffer->capacity);
}
buffer->shapes[buffer->count++] = shape;
if (buffer->count <= buffer->capacity / 4) {
buffer->capacity /= 2;
buffer->shapes =
realloc(buffer->shapes, sizeof(VektorShape) * buffer->capacity);
}
}
VektorBBox vektor_polyline_get_bbox(VektorPrimitive prim) { VektorBBox vektor_polyline_get_bbox(VektorPrimitive prim) {
float min_x, max_x, min_y, max_y; V2 first = prim.polyline->points[0];
for (size_t i = 0; i < prim.polyline->count; i++) {
V2 p = prim.polyline->points[i]; float min_x = first.x;
float max_x = first.x;
float min_y = first.y;
float max_y = first.y;
for (size_t i = 1; i < prim.polygon->count; i++) {
V2 p = prim.polygon->points[i];
min_x = fminf(min_x, p.x); min_x = fminf(min_x, p.x);
min_y = fminf(min_y, p.y); min_y = fminf(min_y, p.y);
max_x = fminf(max_x, p.x); max_x = fmaxf(max_x, p.x);
max_y = fminf(max_y, p.y); max_y = fmaxf(max_y, p.y);
} }
return (VektorBBox){(V2){min_x, min_y}, (V2){max_x, max_y}}; return (VektorBBox){(V2){min_x, min_y}, (V2){max_x, max_y}};
} }
@@ -144,6 +144,13 @@ VektorBBox vektor_rectangle_get_bbox(VektorPrimitive prim) {
return (VektorBBox){prim.rectangle.start, prim.rectangle.end}; return (VektorBBox){prim.rectangle.start, prim.rectangle.end};
} }
VektorBBox vektor_circle_get_bbox(VektorPrimitive prim) {
return (VektorBBox){
vec2_sub(prim.circle.center, vec2_fromfloat(prim.circle.radius)),
vec2_add(prim.circle.center, vec2_fromfloat(prim.circle.radius))
};
}
VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim) { VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim) {
switch (prim.kind) { switch (prim.kind) {
case VEKTOR_POLYLINE: case VEKTOR_POLYLINE:
@@ -158,17 +165,177 @@ VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim) {
return vektor_rectangle_get_bbox(prim); return vektor_rectangle_get_bbox(prim);
break; break;
case VEKTOR_CIRCLE:
return vektor_circle_get_bbox(prim);
break;
default: default:
// TODO: fill in all primitives // TODO: fill in all primitives
break; break;
} }
} }
// ------ PRIMITIVE HANDLES GENERATION ------
/* [n]: polyline vertices */
void vektor_polyline_create_handles(VektorPolyline* polyline, V2** handleArr, size_t* count) {
*count = 0;
*handleArr = NULL;
}
/* [n]: polygon vertices */
void vektor_polygon_create_handles(VektorPolygon* polygon, V2** handleArr, size_t* count) {
*count = 0;
*handleArr = NULL;
}
/* [0]: center; [1]: radius */
void vektor_circle_create_handles(VektorCircle* circle, V2** handleArr, size_t* count) {
*count = 2;
*handleArr = (V2*)malloc(sizeof(V2)*(*count));
(*handleArr)[0] = circle->center;
(*handleArr)[1] = (V2){circle->radius + circle->center.x, circle->center.y};
}
/* [0]: center; [1-4]: corners (l2r, t2b); */
void vektor_rectangle_create_handles(VektorRectangle* rectangle, V2** handleArr, size_t* count) {
*count = 5;
free(*handleArr);
*handleArr = (V2*)malloc(sizeof(V2)*(*count));
V2 halfdist = vec2_scale(vec2_sub(rectangle->end, rectangle->start), 0.5f);
V2 center = vec2_add(rectangle->start, halfdist);
(*handleArr)[0] = center;
(*handleArr)[1] = vec2_add( center, vec2_mul(halfdist, (V2){-1.0f, 1.0f}) );
(*handleArr)[2] = vec2_add( center, halfdist);
(*handleArr)[3] = vec2_add( center, vec2_mul(halfdist, (V2){-1.0f, -1.0f}) );
(*handleArr)[4] = vec2_add( center, vec2_mul(halfdist, (V2){1.0f, -1.0f}) );
}
void vektor_shape_create_handles(VektorShape* shape) {
switch(shape->primitive.kind) {
case VEKTOR_POLYLINE:
vektor_polyline_create_handles(shape->primitive.polyline, &shape->handles, &shape->handleCount);
break;
case VEKTOR_POLYGON:
vektor_polygon_create_handles(shape->primitive.polygon, &shape->handles, &shape->handleCount);
break;
case VEKTOR_CIRCLE:
vektor_circle_create_handles(&shape->primitive.circle, &shape->handles, &shape->handleCount);
break;
case VEKTOR_RECTANGLE:
vektor_rectangle_create_handles(&shape->primitive.rectangle, &shape->handles, &shape->handleCount);
break;
}
}
// ------ PRIMITIVE HANDLES UPDATING ------
void vektor_polyline_handles_updated(VektorPolyline* polyline, V2** handles, size_t* count) {
if(*count != polyline->count) {
g_warning("handle count & point count mismatch in polyline");
return;
}
for(size_t i = 0; i < *count; i++) {
polyline->points[i] = (*handles)[i];
}
}
void vektor_polygon_handles_updated(VektorPolygon* polygon, V2** handles, size_t* count) {
if(*count != polygon->count) {
g_warning("handle count & point count mismatch in polygon");
return;
}
for(size_t i = 0; i < *count; i++) {
polygon->points[i] = (*handles)[i];
}
}
void vektor_circle_handles_updated(VektorCircle* circle, V2** handles, size_t* count) {
if(*count != 2) {
g_warning("unexpected circle handle count (%zu)", *count);
return;
}
circle->center = (*handles)[0];
circle->radius = vec2_length(vec2_sub((*handles)[0], (*handles)[1]));
}
void vektor_rectangle_handles_updated(VektorRectangle* rectangle, V2** handles, size_t* count) {
if(*count != 5) {
g_warning("unexpected rectangle handle count (%zu)", *count);
return;
}
// get rectangle center
V2 halfdist = vec2_scale(vec2_sub(rectangle->end, rectangle->start), 0.5f);
V2 rectcenter = vec2_add(rectangle->start, halfdist);
// center according to handles
V2 center = (*handles)[0];
if(vec2_equals(center, rectcenter)) { // corner handles were changed
V2 p1 = (*handles)[1];
V2 p2 = (*handles)[2];
V2 p3 = (*handles)[3];
V2 p4 = (*handles)[4];
float min_x = fminf(p1.x, fminf(p2.x, fminf(p3.x, p4.x)));
float min_y = fminf(p1.y, fminf(p2.y, fminf(p3.y, p4.y)));
float max_x = fmaxf(p1.x, fmaxf(p2.x, fmaxf(p3.x, p4.x)));
float max_y = fmaxf(p1.y, fmaxf(p2.y, fmaxf(p3.y, p4.y)));
V2 min = (V2){min_x, min_y};
V2 max = (V2){max_x, max_y};
VektorRectangle propertRect = (VektorRectangle){min,max};
// overwrite handles array (create_handles() frees the passed one)
vektor_rectangle_create_handles(&propertRect, handles, count);
} else { // corner was dragged
V2 translation = vec2_sub(center, rectcenter);
V2 newmax = vec2_add((*handles)[2], translation);
V2 newmin = vec2_add((*handles)[3], translation);
VektorRectangle propertRect = (VektorRectangle){newmin,newmax};
vektor_rectangle_create_handles(&propertRect, handles, count);
}
}
void vektor_shape_handles_updated(VektorShape* shape) {
switch(shape->primitive.kind) {
case VEKTOR_POLYLINE:
vektor_polyline_handles_updated(shape->primitive.polyline, &shape->handles, &shape->handleCount);
break;
case VEKTOR_POLYGON:
vektor_polygon_handles_updated(shape->primitive.polygon, &shape->handles, &shape->handleCount);
break;
case VEKTOR_CIRCLE:
vektor_circle_handles_updated(&shape->primitive.circle, &shape->handles, &shape->handleCount);
break;
case VEKTOR_RECTANGLE:
vektor_rectangle_handles_updated(&shape->primitive.rectangle, &shape->handles, &shape->handleCount);
break;
}
}
// ------ BBOX METHODS ------
bool vektor_bbox_isinside(VektorBBox bbox, V2 point) { bool vektor_bbox_isinside(VektorBBox bbox, V2 point) {
return point.x >= bbox.min.x && point.y >= bbox.min.y && return point.x >= bbox.min.x && point.y >= bbox.min.y &&
point.x <= bbox.max.x && point.y <= bbox.max.y; point.x <= bbox.max.x && point.y <= bbox.max.y;
} }
VektorBBox vektor_bbox_fromcenter(V2 center, float dist) {
V2 v2dist = vec2_fromfloat(dist);
V2 min = vec2_sub(center, v2dist);
V2 max = vec2_add(center, v2dist);
return (VektorBBox){min,max};
}
// ------ SHAPE METHODS ------
VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style, VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style,
int z_index) { int z_index) {
return (VektorShape){.primitive = prim, return (VektorShape){.primitive = prim,
@@ -183,3 +350,19 @@ void vektor_shapes_update_bbox(VektorShapeBuffer* buffer) {
vektor_primitive_get_bbox(buffer->shapes[i].primitive); vektor_primitive_get_bbox(buffer->shapes[i].primitive);
} }
} }
void vektor_shapebuffer_add_shape(VektorShapeBuffer* buffer,
VektorShape shape) {
if (buffer->count >= buffer->capacity) {
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
buffer->shapes =
realloc(buffer->shapes, sizeof(VektorShape) * buffer->capacity);
}
buffer->shapes[buffer->count++] = shape;
if (buffer->count <= buffer->capacity / 4) {
buffer->capacity /= 2;
buffer->shapes =
realloc(buffer->shapes, sizeof(VektorShape) * buffer->capacity);
}
}

View File

@@ -45,23 +45,6 @@ typedef struct {
}; };
} VektorPrimitive; } VektorPrimitive;
VektorPolyline* vektor_polyline_new(void);
void vektor_polyline_add_point(VektorPolyline* pl, V2 point);
void vektor_polyline_free(VektorPolyline* pl);
VektorPolygon* vektor_polygon_new(void);
void vektor_polygon_add_point(VektorPolygon* pl, V2 point);
void vektor_polygon_free(VektorPolygon* pl);
VektorCircle* vektor_circle_new(void);
void vektor_circle_set_center(VektorCircle* circle, V2 point);
void vektor_circle_set_radius(VektorCircle* circle, double radius);
VektorRectangle* vektor_rectangle_new(void);
void vektor_rectangle_set_end(VektorRectangle* rct, V2 point);
void vektor_rectangle_set_start(VektorRectangle* rct, V2 point);
void vektor_rectangle_free(VektorRectangle* rct);
typedef struct { typedef struct {
VektorColor stroke_color; VektorColor stroke_color;
float stroke_width; float stroke_width;
@@ -77,8 +60,31 @@ typedef struct {
int z_index; int z_index;
VektorBBox bbox; VektorBBox bbox;
VektorPrimitive primitive; VektorPrimitive primitive;
V2* handles;
size_t handleCount;
} VektorShape; } VektorShape;
VektorPolyline* vektor_polyline_new(void);
void vektor_polyline_add_point(VektorPolyline* pl, V2 point);
void vektor_polyline_free(VektorPolyline* pl);
VektorPolygon* vektor_polygon_new(void);
void vektor_polygon_add_point(VektorPolygon* pl, V2 point);
void vektor_polygon_free(VektorPolygon* pl);
VektorCircle* vektor_circle_new(void);
void vektor_circle_set_center(VektorCircle* circle, V2 point);
void vektor_circle_set_radius(VektorCircle* circle, double radius);
void vektor_circle_free(VektorCircle* circle);
VektorRectangle* vektor_rectangle_new(void);
void vektor_rectangle_set_end(VektorRectangle* rct, V2 point);
void vektor_rectangle_set_start(VektorRectangle* rct, V2 point);
void vektor_rectangle_free(VektorRectangle* rct);
VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style, int z_index);
VektorBBox vektor_polyline_get_bbox(VektorPrimitive prim); VektorBBox vektor_polyline_get_bbox(VektorPrimitive prim);
VektorBBox vektor_polygon_get_bbox(VektorPrimitive prim); VektorBBox vektor_polygon_get_bbox(VektorPrimitive prim);
VektorBBox vektor_circle_get_bbox(VektorPrimitive prim); VektorBBox vektor_circle_get_bbox(VektorPrimitive prim);
@@ -86,9 +92,21 @@ VektorBBox vektor_rectangle_get_bbox(VektorPrimitive prim);
VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim); VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim);
bool vektor_bbox_isinside(VektorBBox bbox, V2 point); bool vektor_bbox_isinside(VektorBBox bbox, V2 point);
VektorBBox vektor_bbox_fromcenter(V2 center, float dist);
VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style, // shape handles
int z_index); void vektor_polyline_create_handles(VektorPolyline* polyline, V2** handleArr, size_t* count);
void vektor_polygon_create_handles(VektorPolygon* polygon, V2** handleArr, size_t* count);
void vektor_circle_create_handles(VektorCircle* circle, V2** handleArr, size_t* count);
void vektor_rectangle_create_handles(VektorRectangle* rectangle, V2** handleArr, size_t* count);
void vektor_shape_create_handles(VektorShape* shape);
/* reconstructs the shape based on handles alone */
void vektor_polyline_handles_updated(VektorPolyline* polyline, V2** handles, size_t* count);
void vektor_polygon_handles_updated(VektorPolygon* polygon, V2** handles, size_t* count);
void vektor_circle_handles_updated(VektorCircle* circle, V2** handles, size_t* count);
void vektor_rectangle_handles_updated(VektorRectangle* rectangle, V2** handles, size_t* count);
void vektor_shape_handles_updated(VektorShape* shape);
typedef struct { typedef struct {
VektorShape* shapes; VektorShape* shapes;

View File

@@ -14,6 +14,8 @@ typedef struct {
double z; double z;
} V3; } V3;
static inline V2 vec2_fromfloat(const float f) { return (V2){f,f}; }
static inline V3 vec2_vector(const V2 v) { return (V3){v.x, v.y, 0}; } static inline V3 vec2_vector(const V2 v) { return (V3){v.x, v.y, 0}; }
static inline V3 vec2_point(const V2 v) { return (V3){v.x, v.y, 1}; } static inline V3 vec2_point(const V2 v) { return (V3){v.x, v.y, 1}; }
@@ -46,16 +48,16 @@ static inline double vec2_cross(const V2 a, const V2 b) {
return a.x * b.y - a.y * b.x; return a.x * b.y - a.y * b.x;
} }
static inline double vec2_norm(const V2 v) { static inline double vec2_length(const V2 v) {
return sqrt(v.x * v.x + v.y * v.y); return sqrt(v.x * v.x + v.y * v.y);
} }
static inline double vec2_quadrance(const V2 v) { static inline double vec2_lengthsq(const V2 v) {
return (v.x * v.x + v.y * v.y); return (v.x * v.x + v.y * v.y);
} }
static inline V2 vec2_normalize(const V2 v) { static inline V2 vec2_normalize(const V2 v) {
return vec2_scale(v, 1 / vec2_norm(v)); return vec2_scale(v, 1 / vec2_length(v));
} }
#endif // VECTOR_H_ #endif // VECTOR_H_

View File

@@ -1,19 +1,12 @@
#include "glib.h" #include "glib.h"
#include "gtk/gtk.h" #include "gtk/gtk.h"
#include "src/application/applicationstate.h" #include "src/application/applicationstate.h"
#include "src/core/primitives.h"
#include "stdio.h" #include "stdio.h"
#include "stdlib.h" #include "stdlib.h"
#include "./application/applicationstate.h" #include "./application/applicationstate.h"
#include "./core/raster.h"
#include "./ui/uicontroller.h" #include "./ui/uicontroller.h"
#include "./ui/vektorcanvas.h"
#include "./util/color.h"
static void on_map(GtkWidget* window, gpointer user_data) {
vektor_uictrl_map((VektorWidgetState*)user_data);
}
static int update_callback(gpointer data) { static int update_callback(gpointer data) {
VektorAppState* appstate = (VektorAppState*)data; VektorAppState* appstate = (VektorAppState*)data;
@@ -30,9 +23,6 @@ static void activate(GtkApplication* app, gpointer user_data) {
VektorAppState* app_state = (VektorAppState*)malloc(sizeof(VektorAppState)); VektorAppState* app_state = (VektorAppState*)malloc(sizeof(VektorAppState));
vektor_appstate_new(widget_state, app_state); vektor_appstate_new(widget_state, app_state);
g_signal_connect(widget_state->window, "map", G_CALLBACK(on_map),
widget_state);
g_timeout_add(1, update_callback, app_state); g_timeout_add(1, update_callback, app_state);
gtk_window_present(widget_state->window); gtk_window_present(widget_state->window);

View File

@@ -31,11 +31,6 @@ void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut) {
GtkIconTheme* theme = GtkIconTheme* theme =
gtk_icon_theme_get_for_display(gdk_display_get_default()); gtk_icon_theme_get_for_display(gdk_display_get_default());
/*if (gtk_icon_theme_has_icon(theme, "vektor-circle-symbolic"))
g_print("GTK sees it!\n");
else
g_print("Still invisible...\n");*/
// populate state // populate state
stateOut->window = stateOut->window =
GTK_WINDOW(gtk_builder_get_object(builder, "main_window")); GTK_WINDOW(gtk_builder_get_object(builder, "main_window"));
@@ -75,10 +70,9 @@ void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut) {
gtk_window_set_title(stateOut->window, "Vektor"); gtk_window_set_title(stateOut->window, "Vektor");
gtk_window_set_default_size(stateOut->window, 800, 600); gtk_window_set_default_size(stateOut->window, 800, 600);
// Set dimensions
gtk_paned_set_position(stateOut->workspacePaned, 800 * .7);
gtk_paned_set_position(stateOut->sidepanelPaned, 250);
g_object_unref(builder); g_object_unref(builder);
} }
void vektor_uictrl_map(VektorWidgetState* state) {
gtk_paned_set_position(state->workspacePaned, 800 * .7);
gtk_paned_set_position(state->sidepanelPaned, 250);
}

View File

@@ -188,7 +188,7 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx,
glUniform1f(shader_selection_uTimeLoc, time); glUniform1f(shader_selection_uTimeLoc, time);
glUniform2f(shader_selection_uMinLoc, bbox.min.x, bbox.min.y); glUniform2f(shader_selection_uMinLoc, bbox.min.x, bbox.min.y);
glUniform2f(shader_selection_uMaxLoc, bbox.max.x, bbox.max.y); glUniform2f(shader_selection_uMaxLoc, bbox.max.x, bbox.max.y);
glUniform4f(shader_selection_uC1Loc, 0, 0, 0, 1); glUniform4f(shader_selection_uC1Loc, 0, 0, 0, 0);
glUniform4f(shader_selection_uC2Loc, 0.46, 0.46, 1, 1); glUniform4f(shader_selection_uC2Loc, 0.46, 0.46, 1, 1);
glDrawArrays(GL_TRIANGLES, shape_vertex_count, glDrawArrays(GL_TRIANGLES, shape_vertex_count,