feat(experimental): add selection tool

This commit is contained in:
Beriff
2026-03-10 15:55:02 +07:00
parent 232b5c8f90
commit 1d168f7be4
9 changed files with 65 additions and 18 deletions

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#444444; } .ColorScheme-Highlight { color:#4285f4; } .ColorScheme-NeutralText { color:#ff9800; } .ColorScheme-PositiveText { color:#4caf50; } .ColorScheme-NegativeText { color:#f44336; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3.9960938 1 L 4.0117188 12.535156 L 6.3339844 10.255859 L 6.7714844 9.8242188 L 7.0097656 10.404297 L 8.9023438 15 L 10.363281 14.328125 L 8.3808594 9.7792969 L 8.1347656 9.2128906 L 8.7285156 9.15625 L 11.996094 8.8457031 L 3.9960938 1 z" transform="translate(3 3)"/>
</svg>

After

Width:  |  Height:  |  Size: 719 B

View File

@@ -22,7 +22,11 @@ static void appstate_set_tool(GtkButton* button, gpointer user_data) {
data->state->selectedTool = data->tool; data->state->selectedTool = 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); // (ADD NEW REVEALERS HERE)
gtk_revealer_set_reveal_child(
data->state->widgetState->workspaceRevealerShapes,
FALSE
);
// setting tool also resets selected shape // setting tool also resets selected shape
data->state->selectedShape = NULL; data->state->selectedShape = NULL;
@@ -175,6 +179,19 @@ begin_click_dispatch:
//state->selectedShape = NULL; //state->selectedShape = NULL;
vektor_shapes_update_bbox(state->shapeBuffer); 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) { 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->tool = VektorRectangleTool;
data_rectangletool->revealer = wstate->workspaceRevealerShapes; 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 // populate appstate
stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer)); stateOut->shapeBuffer = malloc(sizeof(VektorShapeBuffer));
*stateOut->shapeBuffer = (VektorShapeBuffer){0}; *stateOut->shapeBuffer = (VektorShapeBuffer){0};
@@ -206,14 +227,16 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
vektor_canvas_init(wstate, stateOut->canvas, renderInfo); vektor_canvas_init(wstate, stateOut->canvas, 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_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_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 // hook subtool revealers to their master buttons
g_signal_connect(G_OBJECT(wstate->workspaceButtonMasterShapes), "clicked", g_signal_connect(G_OBJECT(wstate->workspaceButtonMasterShapes), "clicked",

View File

@@ -7,6 +7,7 @@
#include "src/core/raster.h" #include "src/core/raster.h"
typedef enum VektorAppTool { typedef enum VektorAppTool {
VektorSelectionTool,
VektorLineTool, VektorLineTool,
VektorPolygonTool, VektorPolygonTool,
VektorRectangleTool VektorRectangleTool

View File

@@ -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, 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_primitive_get_bbox(prim)}; return (VektorShape){.primitive = prim, .style = style, .z_index = z_index, .bbox=vektor_primitive_get_bbox(prim)};

View File

@@ -80,6 +80,7 @@ VektorBBox vektor_polygon_get_bbox(VektorPrimitive prim);
VektorBBox vektor_rectangle_get_bbox(VektorPrimitive prim); 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);
VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style, VektorShape vektor_shape_new(VektorPrimitive prim, VektorStyle style,
int z_index); int z_index);

View File

@@ -50,14 +50,16 @@ void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut) {
GTK_BUTTON(gtk_builder_get_object(builder, "button_shapetools")); GTK_BUTTON(gtk_builder_get_object(builder, "button_shapetools"));
stateOut->workspaceRevealerShapes = stateOut->workspaceRevealerShapes =
GTK_REVEALER(gtk_builder_get_object(builder, "shape_revealer")); GTK_REVEALER(gtk_builder_get_object(builder, "shape_revealer"));
stateOut->workspaceButtonLinetool = stateOut->workspaceButtonLineTool =
GTK_BUTTON(gtk_builder_get_object(builder, "button_linetool")); GTK_BUTTON(gtk_builder_get_object(builder, "button_linetool"));
stateOut->workspaceButtonRecttool = stateOut->workspaceButtonRectTool =
GTK_BUTTON(gtk_builder_get_object(builder, "button_rectangletool")); GTK_BUTTON(gtk_builder_get_object(builder, "button_rectangletool"));
stateOut->workspaceButtonCircletool = stateOut->workspaceButtonCircleTool =
GTK_BUTTON(gtk_builder_get_object(builder, "button_circletool")); GTK_BUTTON(gtk_builder_get_object(builder, "button_circletool"));
stateOut->workspaceButtonPolygontool = stateOut->workspaceButtonPolygonTool =
GTK_BUTTON(gtk_builder_get_object(builder, "button_polygontool")); GTK_BUTTON(gtk_builder_get_object(builder, "button_polygontool"));
stateOut->workspaceButtonSelectionTool =
GTK_BUTTON(gtk_builder_get_object(builder, "button_selecttool"));
stateOut->workspaceColorPicker = stateOut->workspaceColorPicker =
VEKTOR_COLOR_WHEEL(gtk_builder_get_object(builder, "color_picker")); VEKTOR_COLOR_WHEEL(gtk_builder_get_object(builder, "color_picker"));

View File

@@ -17,10 +17,11 @@ typedef struct VektorWidgetState {
GtkButton* workspaceButtonMasterShapes; GtkButton* workspaceButtonMasterShapes;
GtkRevealer* workspaceRevealerShapes; GtkRevealer* workspaceRevealerShapes;
GtkButton* workspaceButtonLinetool; GtkButton* workspaceButtonLineTool;
GtkButton* workspaceButtonRecttool; GtkButton* workspaceButtonRectTool;
GtkButton* workspaceButtonCircletool; GtkButton* workspaceButtonCircleTool;
GtkButton* workspaceButtonPolygontool; GtkButton* workspaceButtonPolygonTool;
GtkButton* workspaceButtonSelectionTool;
VektorColorWheel* workspaceColorPicker; VektorColorWheel* workspaceColorPicker;

View File

@@ -139,8 +139,6 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx, VektorCanvasRenderInfo*
(*(renderInfo->selectedShape))->primitive (*(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( vektor_vb_add_quad(
&vb, &vb,
bbox.min, bbox.min,
@@ -184,8 +182,8 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx, VektorCanvasRenderInfo*
glUniformMatrix4fv(shader_selection_uProjMatrixLoc, 1, GL_FALSE, projectionMatrix); glUniformMatrix4fv(shader_selection_uProjMatrixLoc, 1, GL_FALSE, projectionMatrix);
glUniform1f(shader_selection_uTimeLoc, time); glUniform1f(shader_selection_uTimeLoc, time);
glUniform2f(shader_selection_uMinLoc, bbox.min.x, bbox.min.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); // ← this was missing/broken 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, 1);
glUniform4f(shader_selection_uC2Loc, 0.46, 0.46, 1, 1); glUniform4f(shader_selection_uC2Loc, 0.46, 0.46, 1, 1);

View File

@@ -65,6 +65,14 @@
<!--Tool buttons--> <!--Tool buttons-->
<!--Select tool-->
<child>
<object class="GtkButton" id="button_selecttool">
<property name="icon-name">tool-select-symbolic</property>
<property name="halign">start</property>
</object>
</child>
<!--Shape tool (row container)--> <!--Shape tool (row container)-->
<child> <child>
<object class="GtkBox"> <object class="GtkBox">