feat: handle drawing

This commit is contained in:
Beriff
2026-03-11 21:04:11 +07:00
parent ed9aca01e4
commit 562cbc12da
4 changed files with 75 additions and 6 deletions

View File

@@ -131,6 +131,10 @@ begin_click_dispatch:
vektor_polyline_add_point(state->selectedShape->primitive.polyline, vektor_polyline_add_point(state->selectedShape->primitive.polyline,
pos); pos);
vektor_shapes_update_bbox(state->shapeBuffer); vektor_shapes_update_bbox(state->shapeBuffer);
// polyline's handle count is not fixed, so we have to add them manually
vektor_shape_add_handle(state->selectedShape, pos);
} else if (state->selectedTool == VektorPolygonTool) { } else if (state->selectedTool == VektorPolygonTool) {
// create new polygon shape if none is selected // create new polygon shape if none is selected
if (state->selectedShape == NULL) { if (state->selectedShape == NULL) {
@@ -155,6 +159,10 @@ 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);
// polygon's handle count is not fixed, so we have to add them manually
vektor_shape_add_handle(state->selectedShape, pos);
} else if (state->selectedTool == VektorCircleTool) { } else if (state->selectedTool == VektorCircleTool) {
VektorCircle* circle = vektor_circle_new(); VektorCircle* circle = vektor_circle_new();
@@ -174,6 +182,12 @@ begin_click_dispatch:
vektor_circle_set_radius(&state->selectedShape->primitive.circle, 0.1f); vektor_circle_set_radius(&state->selectedShape->primitive.circle, 0.1f);
vektor_shapes_update_bbox(state->shapeBuffer); vektor_shapes_update_bbox(state->shapeBuffer);
vektor_circle_create_handles(
&state->selectedShape->primitive.circle,
&state->selectedShape->handles,
&state->selectedShape->handleCount
);
} else if (state->selectedTool == VektorRectangleTool) { } else if (state->selectedTool == VektorRectangleTool) {
VektorRectangle* rect = vektor_rectangle_new(); VektorRectangle* rect = vektor_rectangle_new();
@@ -193,6 +207,12 @@ begin_click_dispatch:
pos); pos);
vektor_rectangle_set_end(&state->selectedShape->primitive.rectangle, vektor_rectangle_set_end(&state->selectedShape->primitive.rectangle,
vec2_add(pos, (V2){0.1f, 0.1f})); vec2_add(pos, (V2){0.1f, 0.1f}));
vektor_rectangle_create_handles(
&state->selectedShape->primitive.rectangle,
&state->selectedShape->handles,
&state->selectedShape->handleCount
);
// state->selectedShape = NULL; // state->selectedShape = NULL;
vektor_shapes_update_bbox(state->shapeBuffer); vektor_shapes_update_bbox(state->shapeBuffer);
} else if (state->selectedTool == VektorSelectionTool) { } else if (state->selectedTool == VektorSelectionTool) {
@@ -207,6 +227,9 @@ begin_click_dispatch:
// was clicked outside any shapes - reset selection // was clicked outside any shapes - reset selection
state->selectedShape = NULL; state->selectedShape = NULL;
} }
if(state->selectedShape != NULL)
g_print("%zu\n", state->selectedShape->handleCount);
} }
void vektor_appstate_canvas_drag_begin(GtkGestureDrag* gesture, gdouble x, void vektor_appstate_canvas_drag_begin(GtkGestureDrag* gesture, gdouble x,

View File

@@ -205,6 +205,8 @@ void vektor_rectangle_create_handles(VektorRectangle* rectangle, V2** handleArr,
V2 halfdist = vec2_scale(vec2_sub(rectangle->end, rectangle->start), 0.5f); V2 halfdist = vec2_scale(vec2_sub(rectangle->end, rectangle->start), 0.5f);
V2 center = vec2_add(rectangle->start, halfdist); V2 center = vec2_add(rectangle->start, halfdist);
g_print("boobs: %f %f\n", rectangle->start.x, rectangle->start.y);
g_print("pussy: %f %f\n", rectangle->end.x, rectangle->end.y);
(*handleArr)[0] = center; (*handleArr)[0] = center;
(*handleArr)[1] = vec2_add( center, vec2_mul(halfdist, (V2){-1.0f, 1.0f}) ); (*handleArr)[1] = vec2_add( center, vec2_mul(halfdist, (V2){-1.0f, 1.0f}) );
@@ -320,6 +322,15 @@ void vektor_shape_handles_updated(VektorShape* shape) {
} }
} }
void vektor_shape_add_handle(VektorShape* shape, V2 handle) {
// could be optimised with capacity property
// but this function is only called when adding new
// points to polyline and polygon, so it should
// not be that much of an overhead
shape->handles = realloc(shape->handles, sizeof(V2) * shape->handleCount + 1);
shape->handles[shape->handleCount++] = handle;
}
// ------ BBOX METHODS ------ // ------ BBOX METHODS ------
bool vektor_bbox_isinside(VektorBBox bbox, V2 point) { bool vektor_bbox_isinside(VektorBBox bbox, V2 point) {
@@ -334,14 +345,29 @@ VektorBBox vektor_bbox_fromcenter(V2 center, float dist) {
return (VektorBBox){min,max}; return (VektorBBox){min,max};
} }
VektorBBox vektor_bbox_expand(VektorBBox bbox, float val) {
return (VektorBBox){
vec2_sub(bbox.min, vec2_fromfloat(val)),
vec2_add(bbox.max, vec2_fromfloat(val))
};
}
// ------ SHAPE METHODS ------ // ------ 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, VektorShape shape = (VektorShape){.primitive = prim,
.style = style, .style = style,
.z_index = z_index, .z_index = z_index,
.bbox = vektor_primitive_get_bbox(prim)}; .bbox = vektor_primitive_get_bbox(prim)};
/*
create_handles() allocates new buffer for handles,
and even if the local shape variable goes out of scope and deallocates,
the passed value's pointer to an array of handles remains valid in the passed copy.
*/
vektor_shape_create_handles(&shape);
return shape;
} }
void vektor_shapes_update_bbox(VektorShapeBuffer* buffer) { void vektor_shapes_update_bbox(VektorShapeBuffer* buffer) {

View File

@@ -93,6 +93,7 @@ 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); VektorBBox vektor_bbox_fromcenter(V2 center, float dist);
VektorBBox vektor_bbox_expand(VektorBBox bbox, float val);
// shape handles // shape handles
void vektor_polyline_create_handles(VektorPolyline* polyline, V2** handleArr, size_t* count); void vektor_polyline_create_handles(VektorPolyline* polyline, V2** handleArr, size_t* count);
@@ -100,6 +101,7 @@ void vektor_polygon_create_handles(VektorPolygon* polygon, V2** handleArr, size_
void vektor_circle_create_handles(VektorCircle* circle, 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_rectangle_create_handles(VektorRectangle* rectangle, V2** handleArr, size_t* count);
void vektor_shape_create_handles(VektorShape* shape); void vektor_shape_create_handles(VektorShape* shape);
void vektor_shape_add_handle(VektorShape* shape, V2 handle);
/* reconstructs the shape based on handles alone */ /* reconstructs the shape based on handles alone */
void vektor_polyline_handles_updated(VektorPolyline* polyline, V2** handles, size_t* count); void vektor_polyline_handles_updated(VektorPolyline* polyline, V2** handles, size_t* count);

View File

@@ -140,19 +140,36 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx,
vb.count = 0; vb.count = 0;
vektor_rasterize(&vb, renderInfo->shapes, renderInfo->zoom); vektor_rasterize(&vb, renderInfo->shapes, renderInfo->zoom);
size_t shape_vertex_count = size_t shape_vertex_count = vb.count; // remember how many vertices belong to shapes
vb.count; // remember how many vertices belong to shapes
// create selection quad if a shape is selected
if (renderInfo->selectedShape != NULL && if (renderInfo->selectedShape != NULL &&
*(renderInfo->selectedShape) != NULL) { *(renderInfo->selectedShape) != NULL) {
VektorBBox bbox = vektor_primitive_get_bbox(
(*(renderInfo->selectedShape))->primitive); VektorShape* selectedShape = *renderInfo->selectedShape;
// create handle quads if a shape is selected
for(size_t i = 0; i < selectedShape->handleCount; i++) {
V2 handle = selectedShape->handles[i];
VektorBBox handleBbox = vektor_bbox_fromcenter(handle, 0.01f);
vektor_vb_add_quad(&vb, handleBbox.min, handleBbox.max, vektor_color_new(255, 255, 255, 255));
}
shape_vertex_count = vb.count;
// create selection quad if a shape is selected
VektorBBox bbox = vektor_primitive_get_bbox(selectedShape->primitive);
// expand it a little so it is not inset
bbox = vektor_bbox_expand(bbox, 0.03f);
vektor_vb_add_quad(&vb, bbox.min, bbox.max, vektor_vb_add_quad(&vb, bbox.min, bbox.max,
vektor_color_new(255, 255, 255, 255)); vektor_color_new(255, 255, 255, 255));
} }
glBufferData(GL_ARRAY_BUFFER, vb.count * sizeof(Vertex), vb.vertices, glBufferData(GL_ARRAY_BUFFER, vb.count * sizeof(Vertex), vb.vertices,
GL_STATIC_DRAW); GL_STATIC_DRAW);
@@ -180,6 +197,7 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx,
// re-fetch bbox (we know a shape is selected) // re-fetch bbox (we know a shape is selected)
VektorBBox bbox = vektor_primitive_get_bbox( VektorBBox bbox = vektor_primitive_get_bbox(
(*(renderInfo->selectedShape))->primitive); (*(renderInfo->selectedShape))->primitive);
bbox = vektor_bbox_expand(bbox, 0.03f);
glUseProgram(selection_shader_program); glUseProgram(selection_shader_program);