From 858a1f2c1a86bed59779a0c34db709e9f557c743 Mon Sep 17 00:00:00 2001 From: Froxwin <56168224+Froxwin@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:27:52 +0000 Subject: [PATCH] feat: add canvas zoom --- src/application/applicationstate.c | 3 +++ src/core/matrix.c | 22 +++++++++++++++ src/core/matrix.h | 2 ++ src/ui/vektorcanvas.c | 43 +++++++++++++++++++++++++----- src/ui/vektorcanvas.h | 2 ++ 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/application/applicationstate.c b/src/application/applicationstate.c index c75354d..fb3c9c5 100644 --- a/src/application/applicationstate.c +++ b/src/application/applicationstate.c @@ -1,3 +1,4 @@ +#include "src/core/matrix.h" #include "src/ui/uicontroller.h" #include "stdlib.h" @@ -232,6 +233,8 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) { stateOut->currentColor = vektor_color_solid(0, 0, 0); stateOut->selectedShape = NULL; VektorCanvasRenderInfo* renderInfo = malloc(sizeof(VektorCanvasRenderInfo)); + renderInfo->zoom = 1; + m33_to_gl4(m33_identity(), renderInfo->canvasTransform); renderInfo->selectedShape = &(stateOut->selectedShape); renderInfo->shapes = stateOut->shapeBuffer; renderInfo->startupTime = stateOut->startupTime; diff --git a/src/core/matrix.c b/src/core/matrix.c index 3ab914e..a262e62 100644 --- a/src/core/matrix.c +++ b/src/core/matrix.c @@ -87,3 +87,25 @@ V2 m33_transform(const M33 mat, const V2 v) { return (V2){mat.m[0][0] * v.x + mat.m[0][1] * v.y + mat.m[0][2], mat.m[1][0] * v.x + mat.m[1][1] * v.y + mat.m[1][2]}; } + +void m33_to_gl4(const M33 m, float out[16]) { + out[0] = m.m[0][0]; + out[1] = m.m[1][0]; + out[2] = 0.0f; + out[3] = 0.0f; + + out[4] = m.m[0][1]; + out[5] = m.m[1][1]; + out[6] = 0.0f; + out[7] = 0.0f; + + out[8] = 0.0f; + out[9] = 0.0f; + out[10] = 1.0f; + out[11] = 0.0f; + + out[12] = m.m[0][2]; + out[13] = m.m[1][2]; + out[14] = 0.0f; + out[15] = 1.0f; +} \ No newline at end of file diff --git a/src/core/matrix.h b/src/core/matrix.h index 10a47f1..c919528 100644 --- a/src/core/matrix.h +++ b/src/core/matrix.h @@ -22,4 +22,6 @@ M33 m33_inverse(const M33 m); V2 m33_transform(const M33 mat, const V2 v); +void m33_to_gl4(const M33 m, float out[16]); + #endif // MATRIX_H_ diff --git a/src/ui/vektorcanvas.c b/src/ui/vektorcanvas.c index c10a427..7b38c1c 100644 --- a/src/ui/vektorcanvas.c +++ b/src/ui/vektorcanvas.c @@ -3,6 +3,7 @@ #include "gtk/gtk.h" #include "../core/raster.h" +#include "src/core/matrix.h" #include "src/core/primitives.h" #include "src/util/color.h" #include "uicontroller.h" @@ -158,10 +159,10 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx, // PASS 1 - draw shape vertices glUseProgram(standard_shader_program); - float projectionMatrix[16] = {1, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 1}; + // float projectionMatrix[16] = {1, 0, 0, 0, 0, 1, 0, 0, + // 0, 0, 1, 0, 0, 0, 0, 1}; glUniformMatrix4fv(shader_standard_uProjMatrixLoc, 1, GL_FALSE, - projectionMatrix); + renderInfo->canvasTransform); glBindVertexArray(vao); glDisable(GL_CULL_FACE); @@ -182,11 +183,8 @@ static gboolean render(GtkGLArea* a, GdkGLContext* ctx, glUseProgram(selection_shader_program); - float projectionMatrix[16] = {1, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 1}; - glUniformMatrix4fv(shader_selection_uProjMatrixLoc, 1, GL_FALSE, - projectionMatrix); + renderInfo->canvasTransform); glUniform1f(shader_selection_uTimeLoc, time); glUniform2f(shader_selection_uMinLoc, bbox.min.x, bbox.min.y); glUniform2f(shader_selection_uMaxLoc, bbox.max.x, bbox.max.y); @@ -241,6 +239,30 @@ static void realize(GtkGLArea* area, gpointer user_data) { init_geometry(); } +static void on_scroll(GtkEventControllerScroll* controller, double dx, + double dy, gpointer user_data) { + VektorCanvasRenderInfo* s = user_data; + + GdkModifierType state = gtk_event_controller_get_current_event_state( + GTK_EVENT_CONTROLLER(controller)); + + if (state & GDK_CONTROL_MASK) { + + if (dy < 0) + s->zoom *= 0.9f; + else if (dy > 0) + s->zoom *= 1.1f; + + M33 mat = m33_scale(s->zoom, s->zoom); + + m33_to_gl4(mat, s->canvasTransform); + + GtkWidget* widget = + gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(controller)); + gtk_gl_area_queue_render(GTK_GL_AREA(widget)); + } +} + void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut, VektorCanvasRenderInfo* renderInfo) { canvasOut->canvasWidget = state->workspaceCanvas; @@ -258,4 +280,11 @@ void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut, NULL); g_signal_connect(canvasOut->canvasWidget, "render", G_CALLBACK(render), renderInfo); + + GtkEventController* scroll = + gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_VERTICAL); + + gtk_widget_add_controller(GTK_WIDGET(canvasOut->canvasWidget), scroll); + + g_signal_connect(scroll, "scroll", G_CALLBACK(on_scroll), renderInfo); } diff --git a/src/ui/vektorcanvas.h b/src/ui/vektorcanvas.h index 540e000..e70c05e 100644 --- a/src/ui/vektorcanvas.h +++ b/src/ui/vektorcanvas.h @@ -25,6 +25,8 @@ typedef struct VektorCanvasRenderInfo { // a pointer to appstate->selectedShape VektorShape** selectedShape; + float zoom; + float canvasTransform[16]; } VektorCanvasRenderInfo; void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut,