feat(experimental): add rectangle shape support
This commit is contained in:
@@ -21,6 +21,8 @@ static void appstate_set_tool(GtkButton* button, gpointer user_data) {
|
|||||||
button_tool_set_data* data = (button_tool_set_data*)user_data;
|
button_tool_set_data* data = (button_tool_set_data*)user_data;
|
||||||
data->state->selectedTool = data->tool;
|
data->state->selectedTool = data->tool;
|
||||||
|
|
||||||
|
g_print("%d", data->tool);
|
||||||
|
|
||||||
// setting tool makes the sub-tools menu to close
|
// setting tool makes the sub-tools menu to close
|
||||||
gtk_revealer_set_reveal_child(data->revealer, FALSE);
|
gtk_revealer_set_reveal_child(data->revealer, FALSE);
|
||||||
|
|
||||||
@@ -152,6 +154,30 @@ 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);
|
vektor_shapes_update_bbox(state->shapeBuffer);
|
||||||
}
|
}
|
||||||
|
else if (state->selectedTool == VektorRectangleTool) {
|
||||||
|
|
||||||
|
VektorRectangle* rect = vektor_rectangle_new();
|
||||||
|
VektorPrimitive rectPrimitive =
|
||||||
|
(VektorPrimitive){.kind = VEKTOR_RECTANGLE, .rectangle = *rect};
|
||||||
|
VektorStyle style = (VektorStyle){
|
||||||
|
.stroke_color = state->currentColor, .stroke_width = 0.01};
|
||||||
|
vektor_shapebuffer_add_shape(
|
||||||
|
state->shapeBuffer, vektor_shape_new(rectPrimitive, style, 0));
|
||||||
|
|
||||||
|
state->selectedShape =
|
||||||
|
&(state->shapeBuffer->shapes[state->shapeBuffer->count - 1]);
|
||||||
|
|
||||||
|
vektor_rectangle_free(rect);
|
||||||
|
|
||||||
|
|
||||||
|
vektor_rectangle_set_start(&state->selectedShape->primitive.rectangle, pos);
|
||||||
|
vektor_rectangle_set_end(
|
||||||
|
&state->selectedShape->primitive.rectangle,
|
||||||
|
vec2_add(pos, (V2){0.1f,-0.1f})
|
||||||
|
);
|
||||||
|
//state->selectedShape = NULL;
|
||||||
|
vektor_shapes_update_bbox(state->shapeBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
|
void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
|
||||||
@@ -165,6 +191,11 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
|
|||||||
data_polygontool->tool = VektorPolygonTool;
|
data_polygontool->tool = VektorPolygonTool;
|
||||||
data_polygontool->revealer = wstate->workspaceRevealerShapes;
|
data_polygontool->revealer = wstate->workspaceRevealerShapes;
|
||||||
|
|
||||||
|
button_tool_set_data* data_rectangletool = malloc(sizeof(button_tool_set_data));
|
||||||
|
data_rectangletool->state = stateOut;
|
||||||
|
data_rectangletool->tool = VektorRectangleTool;
|
||||||
|
data_rectangletool->revealer = wstate->workspaceRevealerShapes;
|
||||||
|
|
||||||
// populate appstate
|
// populate appstate
|
||||||
stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer));
|
stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer));
|
||||||
*stateOut->shapeBuffer = (VektorShapeBuffer){0};
|
*stateOut->shapeBuffer = (VektorShapeBuffer){0};
|
||||||
@@ -178,7 +209,7 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
|
|||||||
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_linetool);
|
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_linetool);
|
||||||
g_signal_connect(G_OBJECT(wstate->workspaceButtonPolygontool), "clicked",
|
g_signal_connect(G_OBJECT(wstate->workspaceButtonPolygontool), "clicked",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
typedef enum VektorAppTool {
|
typedef enum VektorAppTool {
|
||||||
VektorLineTool,
|
VektorLineTool,
|
||||||
VektorPolygonTool,
|
VektorPolygonTool,
|
||||||
|
VektorRectangleTool
|
||||||
} VektorAppTool;
|
} VektorAppTool;
|
||||||
|
|
||||||
typedef struct VektorAppState {
|
typedef struct VektorAppState {
|
||||||
|
|||||||
@@ -49,6 +49,24 @@ void vektor_polygon_free(VektorPolygon* pg) {
|
|||||||
free(pg);
|
free(pg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VektorRectangle* vektor_rectangle_new(void) {
|
||||||
|
VektorRectangle* rct = malloc(sizeof(VektorRectangle));
|
||||||
|
rct->start = (V2){.x = 0, .y = 0};
|
||||||
|
rct->end = (V2){.x = 0, .y = 0};
|
||||||
|
return rct;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vektor_rectangle_set_end(VektorRectangle* rct, V2 point) {
|
||||||
|
rct->end = point;
|
||||||
|
}
|
||||||
|
void vektor_rectangle_set_start(VektorRectangle* rct, V2 point) {
|
||||||
|
rct->start = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vektor_rectangle_free(VektorRectangle* rct) {
|
||||||
|
free(rct);
|
||||||
|
}
|
||||||
|
|
||||||
void vektor_shapebuffer_add_shape(VektorShapeBuffer* buffer,
|
void vektor_shapebuffer_add_shape(VektorShapeBuffer* buffer,
|
||||||
VektorShape shape) {
|
VektorShape shape) {
|
||||||
if (buffer->count >= buffer->capacity) {
|
if (buffer->count >= buffer->capacity) {
|
||||||
@@ -59,7 +77,7 @@ void vektor_shapebuffer_add_shape(VektorShapeBuffer* buffer,
|
|||||||
buffer->shapes[buffer->count++] = shape;
|
buffer->shapes[buffer->count++] = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
VektorBBox polyline_mk_bbox(VektorPrimitive prim) {
|
VektorBBox vektor_polyline_get_bbox(VektorPrimitive prim) {
|
||||||
float min_x, max_x, min_y, max_y;
|
float min_x, max_x, min_y, max_y;
|
||||||
for (size_t i = 0; i < prim.polyline->count; i++) {
|
for (size_t i = 0; i < prim.polyline->count; i++) {
|
||||||
V2 p = prim.polyline->points[i];
|
V2 p = prim.polyline->points[i];
|
||||||
@@ -72,7 +90,7 @@ VektorBBox polyline_mk_bbox(VektorPrimitive prim) {
|
|||||||
return (VektorBBox){(V2){min_x, min_y}, (V2){max_x, max_y}};
|
return (VektorBBox){(V2){min_x, min_y}, (V2){max_x, max_y}};
|
||||||
}
|
}
|
||||||
|
|
||||||
VektorBBox polygon_mk_bbox(VektorPrimitive prim) {
|
VektorBBox vektor_polygon_get_bbox(VektorPrimitive prim) {
|
||||||
float min_x, max_x, min_y, max_y;
|
float min_x, max_x, min_y, max_y;
|
||||||
for (size_t i = 0; i < prim.polygon->count; i++) {
|
for (size_t i = 0; i < prim.polygon->count; i++) {
|
||||||
V2 p = prim.polygon->points[i];
|
V2 p = prim.polygon->points[i];
|
||||||
@@ -85,14 +103,22 @@ VektorBBox polygon_mk_bbox(VektorPrimitive prim) {
|
|||||||
return (VektorBBox){(V2){min_x, min_y}, (V2){max_x, max_y}};
|
return (VektorBBox){(V2){min_x, min_y}, (V2){max_x, max_y}};
|
||||||
}
|
}
|
||||||
|
|
||||||
VektorBBox vektor_mk_bbox(VektorPrimitive prim) {
|
VektorBBox vektor_rectangle_get_bbox(VektorPrimitive prim) {
|
||||||
|
return *(VektorBBox*)&prim.rectangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim) {
|
||||||
switch (prim.kind) {
|
switch (prim.kind) {
|
||||||
case VEKTOR_POLYLINE:
|
case VEKTOR_POLYLINE:
|
||||||
return polyline_mk_bbox(prim);
|
return vektor_polyline_get_bbox(prim);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VEKTOR_POLYGON:
|
case VEKTOR_POLYGON:
|
||||||
return polygon_mk_bbox(prim);
|
return vektor_polygon_get_bbox(prim);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VEKTOR_RECTANGLE:
|
||||||
|
return vektor_rectangle_get_bbox(prim);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -103,11 +129,11 @@ VektorBBox vektor_mk_bbox(VektorPrimitive prim) {
|
|||||||
|
|
||||||
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, .style = style, .z_index = z_index, .bbox=vektor_mk_bbox(prim)};
|
return (VektorShape){.primitive = prim, .style = style, .z_index = z_index, .bbox=vektor_primitive_get_bbox(prim)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_shapes_update_bbox(VektorShapeBuffer* buffer) {
|
void vektor_shapes_update_bbox(VektorShapeBuffer* buffer) {
|
||||||
for (size_t i = 0; i < buffer->count; i++) {
|
for (size_t i = 0; i < buffer->count; i++) {
|
||||||
buffer->shapes[i].bbox = vektor_mk_bbox(buffer->shapes[i].primitive);
|
buffer->shapes[i].bbox = vektor_primitive_get_bbox(buffer->shapes[i].primitive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,10 +23,16 @@ typedef struct {
|
|||||||
double radius;
|
double radius;
|
||||||
} VektorCircle;
|
} VektorCircle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
V2 start;
|
||||||
|
V2 end;
|
||||||
|
} VektorRectangle;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VEKTOR_POLYLINE,
|
VEKTOR_POLYLINE,
|
||||||
VEKTOR_POLYGON,
|
VEKTOR_POLYGON,
|
||||||
VEKTOR_CIRCLE
|
VEKTOR_CIRCLE,
|
||||||
|
VEKTOR_RECTANGLE
|
||||||
} VektorPrimitiveKind;
|
} VektorPrimitiveKind;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -35,6 +41,7 @@ typedef struct {
|
|||||||
VektorPolyline* polyline;
|
VektorPolyline* polyline;
|
||||||
VektorPolygon* polygon;
|
VektorPolygon* polygon;
|
||||||
VektorCircle circle;
|
VektorCircle circle;
|
||||||
|
VektorRectangle rectangle;
|
||||||
};
|
};
|
||||||
} VektorPrimitive;
|
} VektorPrimitive;
|
||||||
|
|
||||||
@@ -46,6 +53,11 @@ VektorPolygon* vektor_polygon_new(void);
|
|||||||
void vektor_polygon_add_point(VektorPolygon* pl, V2 point);
|
void vektor_polygon_add_point(VektorPolygon* pl, V2 point);
|
||||||
void vektor_polygon_free(VektorPolygon* pl);
|
void vektor_polygon_free(VektorPolygon* pl);
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -63,10 +75,11 @@ typedef struct {
|
|||||||
VektorPrimitive primitive;
|
VektorPrimitive primitive;
|
||||||
} VektorShape;
|
} VektorShape;
|
||||||
|
|
||||||
VektorBBox polyline_mk_bbox(VektorPrimitive prim);
|
VektorBBox vektor_polyline_get_bbox(VektorPrimitive prim);
|
||||||
VektorBBox polygon_mk_bbox(VektorPrimitive prim);
|
VektorBBox vektor_polygon_get_bbox(VektorPrimitive prim);
|
||||||
|
VektorBBox vektor_rectangle_get_bbox(VektorPrimitive prim);
|
||||||
|
|
||||||
VektorBBox vektor_mk_bbox(VektorPrimitive prim);
|
VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim);
|
||||||
|
|
||||||
VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style,
|
VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style,
|
||||||
int z_index);
|
int z_index);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ void vektor_edgebuffer_add_edge(EdgeBuffer* buffer, Edge edge) {
|
|||||||
buffer->edges[buffer->count++] = edge;
|
buffer->edges[buffer->count++] = edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_polyline_flatten(EdgeBuffer* buffer, VektorPolyline* line,
|
void vektor_polyline_tessellate(EdgeBuffer* buffer, VektorPolyline* line,
|
||||||
size_t j) {
|
size_t j) {
|
||||||
for (size_t i = 0; i + 1 < line->count; i++) {
|
for (size_t i = 0; i + 1 < line->count; i++) {
|
||||||
vektor_edgebuffer_add_edge(
|
vektor_edgebuffer_add_edge(
|
||||||
@@ -20,7 +20,7 @@ void vektor_polyline_flatten(EdgeBuffer* buffer, VektorPolyline* line,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_polygon_flatten(EdgeBuffer* buffer, VektorPolygon* polygon,
|
void vektor_polygon_tessellate(EdgeBuffer* buffer, VektorPolygon* polygon,
|
||||||
size_t j) {
|
size_t j) {
|
||||||
for (size_t i = 0; i + 1 < polygon->count; i++) {
|
for (size_t i = 0; i + 1 < polygon->count; i++) {
|
||||||
vektor_edgebuffer_add_edge(
|
vektor_edgebuffer_add_edge(
|
||||||
@@ -30,6 +30,20 @@ void vektor_polygon_flatten(EdgeBuffer* buffer, VektorPolygon* polygon,
|
|||||||
buffer, (Edge){polygon->points[polygon->count - 1], polygon->points[0], 0, j});
|
buffer, (Edge){polygon->points[polygon->count - 1], polygon->points[0], 0, j});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vektor_rectangle_tessellate(EdgeBuffer* buffer, VektorRectangle* rct, size_t j) {
|
||||||
|
if (vec2_equals(rct->end, rct->start)) {return;}
|
||||||
|
|
||||||
|
Edge top = (Edge){rct->start, (V2){rct->end.x, rct->start.y}, 0, j };
|
||||||
|
Edge right = (Edge){(V2){rct->end.x, rct->start.y}, rct->end, 0, j};
|
||||||
|
Edge bottom = (Edge){(V2){rct->start.x, rct->end.y}, rct->end, 0, j};
|
||||||
|
Edge left = (Edge){rct->start, (V2){rct->start.x, rct->end.y}, 0, j };
|
||||||
|
|
||||||
|
vektor_edgebuffer_add_edge(buffer, top);
|
||||||
|
vektor_edgebuffer_add_edge(buffer, right);
|
||||||
|
vektor_edgebuffer_add_edge(buffer, bottom);
|
||||||
|
vektor_edgebuffer_add_edge(buffer, left);
|
||||||
|
}
|
||||||
|
|
||||||
void vektor_rasterize(VertexBuffer* vb, VektorShapeBuffer* shapes) {
|
void vektor_rasterize(VertexBuffer* vb, VektorShapeBuffer* shapes) {
|
||||||
EdgeBuffer edges = {0};
|
EdgeBuffer edges = {0};
|
||||||
for (size_t i = 0; i < shapes->count; i++) {
|
for (size_t i = 0; i < shapes->count; i++) {
|
||||||
@@ -37,11 +51,15 @@ void vektor_rasterize(VertexBuffer* vb, VektorShapeBuffer* shapes) {
|
|||||||
|
|
||||||
switch (p->kind) {
|
switch (p->kind) {
|
||||||
case VEKTOR_POLYLINE:
|
case VEKTOR_POLYLINE:
|
||||||
vektor_polyline_flatten(&edges, p->polyline, i);
|
vektor_polyline_tessellate(&edges, p->polyline, i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VEKTOR_POLYGON:
|
case VEKTOR_POLYGON:
|
||||||
vektor_polygon_flatten(&edges, p->polygon, i);
|
vektor_polygon_tessellate(&edges, p->polygon, i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VEKTOR_RECTANGLE:
|
||||||
|
vektor_rectangle_tessellate(&edges, &p->rectangle, i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ typedef struct {
|
|||||||
|
|
||||||
void vektor_edgebuffer_add_edge(EdgeBuffer* edges, Edge edge);
|
void vektor_edgebuffer_add_edge(EdgeBuffer* edges, Edge edge);
|
||||||
|
|
||||||
void vektor_polyline_flatten(EdgeBuffer* edges, VektorPolyline* line, size_t i);
|
void vektor_polyline_tessellate(EdgeBuffer* edges, VektorPolyline* line, size_t i);
|
||||||
void vektor_polygon_flatten(EdgeBuffer* buffer, VektorPolygon* line, size_t i);
|
void vektor_polygon_tessellate(EdgeBuffer* buffer, VektorPolygon* polygon, size_t i);
|
||||||
|
void vektor_rectangle_tessellate(EdgeBuffer* buffer, VektorRectangle* rct, size_t i);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
V2 coords;
|
V2 coords;
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ static inline V2 vec2_add(const V2 v1, const V2 v2) {
|
|||||||
return (V2){v1.x + v2.x, v1.y + v2.y};
|
return (V2){v1.x + v2.x, v1.y + v2.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool vec2_equals(const V2 v1, const V2 v2) {
|
||||||
|
return (bool)(v1.x == v2.x && v1.y == v2.x);
|
||||||
|
}
|
||||||
|
|
||||||
static inline V2 vec2_sub(const V2 v1, const V2 v2) {
|
static inline V2 vec2_sub(const V2 v1, const V2 v2) {
|
||||||
return (V2){v1.x - v2.x, v1.y - v2.y};
|
return (V2){v1.x - v2.x, v1.y - v2.y};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user