feat: add canvas zoom

This commit is contained in:
2026-03-10 16:27:52 +00:00
parent 22b6700768
commit 858a1f2c1a
5 changed files with 65 additions and 7 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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);
}

View File

@@ -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,