From 1d168f7be4af9edeb3e67921f4ff9ee4f270f8de Mon Sep 17 00:00:00 2001 From: Beriff Date: Tue, 10 Mar 2026 15:55:02 +0700 Subject: [PATCH] feat(experimental): add selection tool --- .../scalable/actions/tool-select-symbolic.svg | 8 +++++ src/application/applicationstate.c | 33 ++++++++++++++++--- src/application/applicationstate.h | 3 +- src/core/primitives.c | 5 +++ src/core/primitives.h | 1 + src/ui/uicontroller.c | 10 +++--- src/ui/uicontroller.h | 9 ++--- src/ui/vektorcanvas.c | 6 ++-- ui/main.ui | 8 +++++ 9 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 icons/hicolor/scalable/actions/tool-select-symbolic.svg diff --git a/icons/hicolor/scalable/actions/tool-select-symbolic.svg b/icons/hicolor/scalable/actions/tool-select-symbolic.svg new file mode 100644 index 0000000..8755b1d --- /dev/null +++ b/icons/hicolor/scalable/actions/tool-select-symbolic.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/application/applicationstate.c b/src/application/applicationstate.c index 78dff57..3e88952 100644 --- a/src/application/applicationstate.c +++ b/src/application/applicationstate.c @@ -22,7 +22,11 @@ static void appstate_set_tool(GtkButton* button, gpointer user_data) { data->state->selectedTool = data->tool; // setting tool makes the sub-tools menu to close - gtk_revealer_set_reveal_child(data->revealer, FALSE); + // (ADD NEW REVEALERS HERE) + gtk_revealer_set_reveal_child( + data->state->widgetState->workspaceRevealerShapes, + FALSE + ); // setting tool also resets selected shape data->state->selectedShape = NULL; @@ -175,6 +179,19 @@ begin_click_dispatch: //state->selectedShape = NULL; vektor_shapes_update_bbox(state->shapeBuffer); } + else if (state->selectedTool == VektorSelectionTool) { + g_print("as select"); + for(size_t i = 0; i < state->shapeBuffer->count; i++) { + VektorBBox bbox = + vektor_primitive_get_bbox(state->shapeBuffer->shapes[i].primitive); + if(vektor_bbox_isinside(bbox, pos)) { + state->selectedShape = &(state->shapeBuffer->shapes[i]); + return; + } + } + // was clicked outside any shapes - reset selection + state->selectedShape = NULL; + } } void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) { @@ -193,6 +210,10 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) { data_rectangletool->tool = VektorRectangleTool; data_rectangletool->revealer = wstate->workspaceRevealerShapes; + button_tool_set_data* data_selecttool = malloc(sizeof(button_tool_set_data)); + data_selecttool->state = stateOut; + data_selecttool->tool = VektorSelectionTool; + // populate appstate stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer)); *stateOut->shapeBuffer = (VektorShapeBuffer){0}; @@ -206,14 +227,16 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) { vektor_canvas_init(wstate, stateOut->canvas, renderInfo); // 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_signal_connect(G_OBJECT(wstate->workspaceButtonRecttool), "clicked", + g_signal_connect(G_OBJECT(wstate->workspaceButtonRectTool), "clicked", 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_signal_connect(G_OBJECT(wstate->workspaceButtonPolygontool), "clicked", + g_signal_connect(G_OBJECT(wstate->workspaceButtonPolygonTool), "clicked", G_CALLBACK(appstate_set_tool), data_polygontool); + g_signal_connect(G_OBJECT(wstate->workspaceButtonSelectionTool), "clicked", + G_CALLBACK(appstate_set_tool), data_selecttool); // hook subtool revealers to their master buttons g_signal_connect(G_OBJECT(wstate->workspaceButtonMasterShapes), "clicked", diff --git a/src/application/applicationstate.h b/src/application/applicationstate.h index 695a362..d009997 100644 --- a/src/application/applicationstate.h +++ b/src/application/applicationstate.h @@ -6,7 +6,8 @@ #include "../ui/vektorcanvas.h" #include "src/core/raster.h" -typedef enum VektorAppTool { +typedef enum VektorAppTool { + VektorSelectionTool, VektorLineTool, VektorPolygonTool, VektorRectangleTool diff --git a/src/core/primitives.c b/src/core/primitives.c index 31a83fd..26c453a 100644 --- a/src/core/primitives.c +++ b/src/core/primitives.c @@ -135,6 +135,11 @@ VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim) { } } +bool vektor_bbox_isinside(VektorBBox bbox, V2 point) { + return point.x >= bbox.min.x && point.y >= bbox.min.y + && point.x <= bbox.max.x && point.y <= bbox.max.y; +} + VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style, int z_index) { return (VektorShape){.primitive = prim, .style = style, .z_index = z_index, .bbox=vektor_primitive_get_bbox(prim)}; diff --git a/src/core/primitives.h b/src/core/primitives.h index ac3d5e5..7897116 100644 --- a/src/core/primitives.h +++ b/src/core/primitives.h @@ -80,6 +80,7 @@ VektorBBox vektor_polygon_get_bbox(VektorPrimitive prim); VektorBBox vektor_rectangle_get_bbox(VektorPrimitive prim); VektorBBox vektor_primitive_get_bbox(VektorPrimitive prim); +bool vektor_bbox_isinside(VektorBBox bbox, V2 point); VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style, int z_index); diff --git a/src/ui/uicontroller.c b/src/ui/uicontroller.c index 5f0a07d..3b076d9 100644 --- a/src/ui/uicontroller.c +++ b/src/ui/uicontroller.c @@ -50,14 +50,16 @@ void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut) { GTK_BUTTON(gtk_builder_get_object(builder, "button_shapetools")); stateOut->workspaceRevealerShapes = GTK_REVEALER(gtk_builder_get_object(builder, "shape_revealer")); - stateOut->workspaceButtonLinetool = + stateOut->workspaceButtonLineTool = GTK_BUTTON(gtk_builder_get_object(builder, "button_linetool")); - stateOut->workspaceButtonRecttool = + stateOut->workspaceButtonRectTool = GTK_BUTTON(gtk_builder_get_object(builder, "button_rectangletool")); - stateOut->workspaceButtonCircletool = + stateOut->workspaceButtonCircleTool = GTK_BUTTON(gtk_builder_get_object(builder, "button_circletool")); - stateOut->workspaceButtonPolygontool = + stateOut->workspaceButtonPolygonTool = GTK_BUTTON(gtk_builder_get_object(builder, "button_polygontool")); + stateOut->workspaceButtonSelectionTool = + GTK_BUTTON(gtk_builder_get_object(builder, "button_selecttool")); stateOut->workspaceColorPicker = VEKTOR_COLOR_WHEEL(gtk_builder_get_object(builder, "color_picker")); diff --git a/src/ui/uicontroller.h b/src/ui/uicontroller.h index bd2a247..90b99b7 100644 --- a/src/ui/uicontroller.h +++ b/src/ui/uicontroller.h @@ -17,10 +17,11 @@ typedef struct VektorWidgetState { GtkButton* workspaceButtonMasterShapes; GtkRevealer* workspaceRevealerShapes; - GtkButton* workspaceButtonLinetool; - GtkButton* workspaceButtonRecttool; - GtkButton* workspaceButtonCircletool; - GtkButton* workspaceButtonPolygontool; + GtkButton* workspaceButtonLineTool; + GtkButton* workspaceButtonRectTool; + GtkButton* workspaceButtonCircleTool; + GtkButton* workspaceButtonPolygonTool; + GtkButton* workspaceButtonSelectionTool; VektorColorWheel* workspaceColorPicker; diff --git a/src/ui/vektorcanvas.c b/src/ui/vektorcanvas.c index 4cf5851..e3ddeda 100644 --- a/src/ui/vektorcanvas.c +++ b/src/ui/vektorcanvas.c @@ -138,8 +138,6 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx, VektorCanvasRenderInfo* VektorBBox bbox = vektor_primitive_get_bbox( (*(renderInfo->selectedShape))->primitive ); - - g_print("min: %f %f max: %f %f\n", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); vektor_vb_add_quad( &vb, @@ -184,8 +182,8 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx, VektorCanvasRenderInfo* glUniformMatrix4fv(shader_selection_uProjMatrixLoc, 1, GL_FALSE, projectionMatrix); glUniform1f(shader_selection_uTimeLoc, time); - glUniform2f(shader_selection_uMinLoc, bbox.min.x, bbox.min.y); // ← this was missing/broken - glUniform2f(shader_selection_uMaxLoc, bbox.max.x, bbox.max.y); // ← this was missing/broken + glUniform2f(shader_selection_uMinLoc, bbox.min.x, bbox.min.y); + glUniform2f(shader_selection_uMaxLoc, bbox.max.x, bbox.max.y); glUniform4f(shader_selection_uC1Loc, 0, 0, 0, 1); glUniform4f(shader_selection_uC2Loc, 0.46, 0.46, 1, 1); diff --git a/ui/main.ui b/ui/main.ui index b254381..0e19809 100644 --- a/ui/main.ui +++ b/ui/main.ui @@ -65,6 +65,14 @@ + + + + tool-select-symbolic + start + + +