feat: add canvas pan and rotate
This commit is contained in:
@@ -103,7 +103,8 @@ static void canvas_onclick(GtkGestureClick* gesture, int n_press, double x,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vektor_appstate_canvas_click(VektorAppState* state, double x, double y) {
|
void vektor_appstate_canvas_click(VektorAppState* state, double x, double y) {
|
||||||
V2 pos = (V2){x, y};
|
V2 pos =
|
||||||
|
m33_transform(m33_inverse(state->renderInfo->canvasMat), (V2){x, y});
|
||||||
|
|
||||||
begin_click_dispatch:
|
begin_click_dispatch:
|
||||||
if (state->selectedTool == VektorLineTool) {
|
if (state->selectedTool == VektorLineTool) {
|
||||||
@@ -234,12 +235,16 @@ void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut) {
|
|||||||
stateOut->selectedShape = NULL;
|
stateOut->selectedShape = NULL;
|
||||||
VektorCanvasRenderInfo* renderInfo = malloc(sizeof(VektorCanvasRenderInfo));
|
VektorCanvasRenderInfo* renderInfo = malloc(sizeof(VektorCanvasRenderInfo));
|
||||||
renderInfo->zoom = 1;
|
renderInfo->zoom = 1;
|
||||||
|
renderInfo->panX = 0;
|
||||||
|
renderInfo->panY = 0;
|
||||||
|
renderInfo->rotation = 0;
|
||||||
m33_to_gl4(m33_identity(), renderInfo->canvasTransform);
|
m33_to_gl4(m33_identity(), renderInfo->canvasTransform);
|
||||||
renderInfo->selectedShape = &(stateOut->selectedShape);
|
renderInfo->selectedShape = &(stateOut->selectedShape);
|
||||||
renderInfo->shapes = stateOut->shapeBuffer;
|
renderInfo->shapes = stateOut->shapeBuffer;
|
||||||
renderInfo->startupTime = stateOut->startupTime;
|
renderInfo->startupTime = stateOut->startupTime;
|
||||||
|
renderInfo->canvasMat = m33_identity();
|
||||||
vektor_canvas_init(wstate, stateOut->canvas, renderInfo);
|
vektor_canvas_init(wstate, stateOut->canvas, renderInfo);
|
||||||
|
stateOut->renderInfo = 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);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ typedef struct VektorAppState {
|
|||||||
VektorShapeBuffer* shapeBuffer;
|
VektorShapeBuffer* shapeBuffer;
|
||||||
// View space
|
// View space
|
||||||
VektorCanvas* canvas;
|
VektorCanvas* canvas;
|
||||||
|
VektorCanvasRenderInfo* renderInfo;
|
||||||
} VektorAppState;
|
} VektorAppState;
|
||||||
|
|
||||||
void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut);
|
void vektor_appstate_new(VektorWidgetState* wstate, VektorAppState* stateOut);
|
||||||
|
|||||||
@@ -246,23 +246,100 @@ static void on_scroll(GtkEventControllerScroll* controller, double dx,
|
|||||||
GdkModifierType state = gtk_event_controller_get_current_event_state(
|
GdkModifierType state = gtk_event_controller_get_current_event_state(
|
||||||
GTK_EVENT_CONTROLLER(controller));
|
GTK_EVENT_CONTROLLER(controller));
|
||||||
|
|
||||||
if (state & GDK_CONTROL_MASK) {
|
// if (state & GDK_CONTROL_MASK) {
|
||||||
|
|
||||||
if (dy < 0)
|
if (dy < 0)
|
||||||
s->zoom *= 0.9f;
|
|
||||||
else if (dy > 0)
|
|
||||||
s->zoom *= 1.1f;
|
s->zoom *= 1.1f;
|
||||||
|
else if (dy > 0)
|
||||||
|
s->zoom *= 0.9f;
|
||||||
|
|
||||||
M33 mat = m33_scale(s->zoom, s->zoom);
|
M33 mat =
|
||||||
|
m33_mul(m33_translate(s->panX, s->panY),
|
||||||
|
m33_mul(m33_rotate(s->rotation), m33_scale(s->zoom, s->zoom)));
|
||||||
|
// M33 mat = m33_mul(m33_mul(m33_scale(s->zoom, s->zoom),
|
||||||
|
// m33_translate(s->panX, s->panY)),
|
||||||
|
// m33_rotate(s->rotation));
|
||||||
m33_to_gl4(mat, s->canvasTransform);
|
m33_to_gl4(mat, s->canvasTransform);
|
||||||
|
s->canvasMat = mat;
|
||||||
|
|
||||||
GtkWidget* widget =
|
GtkWidget* widget =
|
||||||
gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(controller));
|
gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(controller));
|
||||||
gtk_gl_area_queue_render(GTK_GL_AREA(widget));
|
gtk_gl_area_queue_render(GTK_GL_AREA(widget));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_pan_begin(GtkGestureDrag* gesture, double start_x,
|
||||||
|
double start_y, gpointer user_data) {
|
||||||
|
VektorCanvasRenderInfo* s = user_data;
|
||||||
|
|
||||||
|
GdkModifierType state = gtk_event_controller_get_current_event_state(
|
||||||
|
GTK_EVENT_CONTROLLER(gesture));
|
||||||
|
|
||||||
|
if (!(state & GDK_SHIFT_MASK)) {
|
||||||
|
s->drag_start_x = s->panX;
|
||||||
|
s->drag_start_y = s->panY;
|
||||||
|
} else {
|
||||||
|
double x, y;
|
||||||
|
gtk_gesture_drag_get_start_point(gesture, &x, &y);
|
||||||
|
|
||||||
|
s->mouse_start_x = x;
|
||||||
|
s->mouse_start_y = y;
|
||||||
|
|
||||||
|
double cx = VKTR_CANVAS_WIDTH * 0.5;
|
||||||
|
double cy = VKTR_CANVAS_HEIGHT * 0.5;
|
||||||
|
|
||||||
|
double dx = x - cx;
|
||||||
|
double dy = y - cy;
|
||||||
|
|
||||||
|
s->dragStartAngle = atan2(dy, dx);
|
||||||
|
s->dragStartRotation = s->rotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_pan_drag(GtkGestureDrag* gesture, double offset_x,
|
||||||
|
double offset_y, gpointer user_data) {
|
||||||
|
VektorCanvasRenderInfo* s = user_data;
|
||||||
|
|
||||||
|
GdkModifierType state = gtk_event_controller_get_current_event_state(
|
||||||
|
GTK_EVENT_CONTROLLER(gesture));
|
||||||
|
|
||||||
|
if (!(state & GDK_SHIFT_MASK)) {
|
||||||
|
s->panX = s->drag_start_x + offset_x / (80 * s->zoom);
|
||||||
|
s->panY = s->drag_start_y - offset_y / (80 * s->zoom);
|
||||||
|
|
||||||
|
M33 mat = m33_mul(
|
||||||
|
m33_translate(s->panX, s->panY),
|
||||||
|
m33_mul(m33_rotate(s->rotation), m33_scale(s->zoom, s->zoom)));
|
||||||
|
m33_to_gl4(mat, s->canvasTransform);
|
||||||
|
s->canvasMat = mat;
|
||||||
|
} else {
|
||||||
|
double x, y;
|
||||||
|
gtk_gesture_drag_get_offset(gesture, &x, &y);
|
||||||
|
|
||||||
|
double mx = s->mouse_start_x + x;
|
||||||
|
double my = s->mouse_start_y + y;
|
||||||
|
|
||||||
|
double cx = VKTR_CANVAS_WIDTH * 0.5;
|
||||||
|
double cy = VKTR_CANVAS_HEIGHT * 0.5;
|
||||||
|
|
||||||
|
double dx = mx - cx;
|
||||||
|
double dy = my - cy;
|
||||||
|
|
||||||
|
double angle = -atan2(dy, dx);
|
||||||
|
|
||||||
|
s->rotation = s->dragStartRotation + (angle - s->dragStartAngle);
|
||||||
|
|
||||||
|
M33 mat = m33_mul(
|
||||||
|
m33_translate(s->panX, s->panY),
|
||||||
|
m33_mul(m33_rotate(s->rotation), m33_scale(s->zoom, s->zoom)));
|
||||||
|
m33_to_gl4(mat, s->canvasTransform);
|
||||||
|
s->canvasMat = mat;
|
||||||
|
}
|
||||||
|
GtkWidget* widget =
|
||||||
|
gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
|
||||||
|
gtk_gl_area_queue_render(GTK_GL_AREA(widget));
|
||||||
|
}
|
||||||
|
|
||||||
void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut,
|
void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut,
|
||||||
VektorCanvasRenderInfo* renderInfo) {
|
VektorCanvasRenderInfo* renderInfo) {
|
||||||
canvasOut->canvasWidget = state->workspaceCanvas;
|
canvasOut->canvasWidget = state->workspaceCanvas;
|
||||||
@@ -287,4 +364,13 @@ void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut,
|
|||||||
gtk_widget_add_controller(GTK_WIDGET(canvasOut->canvasWidget), scroll);
|
gtk_widget_add_controller(GTK_WIDGET(canvasOut->canvasWidget), scroll);
|
||||||
|
|
||||||
g_signal_connect(scroll, "scroll", G_CALLBACK(on_scroll), renderInfo);
|
g_signal_connect(scroll, "scroll", G_CALLBACK(on_scroll), renderInfo);
|
||||||
|
|
||||||
|
GtkGesture* pan = gtk_gesture_drag_new();
|
||||||
|
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(pan), GDK_BUTTON_MIDDLE);
|
||||||
|
|
||||||
|
gtk_widget_add_controller(GTK_WIDGET(canvasOut->canvasWidget),
|
||||||
|
GTK_EVENT_CONTROLLER(pan));
|
||||||
|
|
||||||
|
g_signal_connect(pan, "drag-begin", G_CALLBACK(on_pan_begin), renderInfo);
|
||||||
|
g_signal_connect(pan, "drag-update", G_CALLBACK(on_pan_drag), renderInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "../core/raster.h"
|
#include "../core/raster.h"
|
||||||
#include "../util/color.h"
|
#include "../util/color.h"
|
||||||
#include "gtk/gtk.h"
|
#include "gtk/gtk.h"
|
||||||
|
#include "src/core/matrix.h"
|
||||||
#include "src/core/primitives.h"
|
#include "src/core/primitives.h"
|
||||||
#include "uicontroller.h"
|
#include "uicontroller.h"
|
||||||
|
|
||||||
@@ -26,6 +27,18 @@ typedef struct VektorCanvasRenderInfo {
|
|||||||
// a pointer to appstate->selectedShape
|
// a pointer to appstate->selectedShape
|
||||||
VektorShape** selectedShape;
|
VektorShape** selectedShape;
|
||||||
float zoom;
|
float zoom;
|
||||||
|
float panX;
|
||||||
|
float panY;
|
||||||
|
float rotation;
|
||||||
|
|
||||||
|
float dragStartRotation;
|
||||||
|
double dragStartAngle;
|
||||||
|
double drag_start_x;
|
||||||
|
double drag_start_y;
|
||||||
|
double mouse_start_x;
|
||||||
|
double mouse_start_y;
|
||||||
|
|
||||||
|
M33 canvasMat;
|
||||||
float canvasTransform[16];
|
float canvasTransform[16];
|
||||||
} VektorCanvasRenderInfo;
|
} VektorCanvasRenderInfo;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user