[Bf-blender-cvs] [07966cbacfc] temp-gpencil-bezier-stroke-type: GPencil: Snap to cursor curves

Falk David noreply at git.blender.org
Mon Mar 15 00:36:25 CET 2021


Commit: 07966cbacfc1fb9e68b7bcac93a4c212c90dd29b
Author: Falk David
Date:   Sun Mar 14 19:09:21 2021 +0100
Branches: temp-gpencil-bezier-stroke-type
https://developer.blender.org/rB07966cbacfc1fb9e68b7bcac93a4c212c90dd29b

GPencil: Snap to cursor curves

Implements snapping curve points to the cursor.
When the control point is selected, the handles are offset,
so they don't snap to a single point.

===================================================================

M	source/blender/editors/gpencil/gpencil_edit.c

===================================================================

diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 3a51cc22ba0..f768f3ad4fc 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3035,7 +3035,6 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
 static int gpencil_snap_to_cursor(bContext *C, wmOperator *op)
 {
   bGPdata *gpd = ED_gpencil_data_get_active(C);
-  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
   Scene *scene = CTX_data_scene(C);
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
   Object *obact = CTX_data_active_object(C);
@@ -3044,53 +3043,118 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op)
   const float *cursor_global = scene->cursor.location;
 
   bool changed = false;
-  if (is_curve_edit) {
-    BKE_report(op->reports, RPT_ERROR, "Not implemented!");
-  }
-  else {
-    LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
-      /* only editable and visible layers are considered */
-      if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
-        bGPDframe *gpf = gpl->actframe;
-        float diff_mat[4][4];
+  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+    /* only editable and visible layers are considered */
+    if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+      bGPDframe *gpf = gpl->actframe;
+      float diff_mat[4][4];
 
-        /* calculate difference matrix */
-        BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
+      /* calculate difference matrix */
+      BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
 
-        LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
-          bGPDspoint *pt;
-          int i;
+      LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+        /* skip strokes that are invalid for current view */
+        if (ED_gpencil_stroke_can_use(C, gps) == false) {
+          continue;
+        }
+        /* check if the color is editable */
+        if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
+          continue;
+        }
 
-          /* skip strokes that are invalid for current view */
-          if (ED_gpencil_stroke_can_use(C, gps) == false) {
-            continue;
+        bool is_stroke_selected = GPENCIL_STROKE_TYPE_BEZIER(gps) ?
+                                      (bool)(gps->editcurve->flag & GP_CURVE_SELECT) :
+                                      (bool)(gps->flag & GP_STROKE_SELECT);
+
+        /* only continue if this stroke is selected (editable doesn't guarantee this)... */
+        if ((is_stroke_selected) == 0) {
+          continue;
+        }
+
+        if (use_offset) {
+          /* TODO: Allow using midpoint instead? */
+          float offset[3];
+
+          /* To avoid recalculating the curve, we will offset the curve data first and then all the
+           * stroke points. */
+          if (GPENCIL_STROKE_TYPE_BEZIER(gps)) {
+            float tmp[3];
+            bGPDcurve *gpc = gps->editcurve;
+            /* Calculate offset. */
+            mul_v3_m4v3(tmp, diff_mat, gpc->curve_points->bezt.vec[1]);
+            sub_v3_v3v3(offset, cursor_global, tmp);
+
+            /* Offset points. */
+            for (int i = 0; i < gpc->tot_curve_points; i++) {
+              bGPDcurve_point *cpt = &gpc->curve_points[i];
+              BezTriple *bezt = &cpt->bezt;
+              for (int j = 0; j < 3; j++) {
+                add_v3_v3(bezt->vec[j], offset);
+              }
+            }
           }
-          /* check if the color is editable */
-          if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
-            continue;
+          else {
+            /* compute offset from first point of stroke to cursor */
+            sub_v3_v3v3(offset, cursor_global, &gps->points->x);
           }
-          /* only continue if this stroke is selected (editable doesn't guarantee this)... */
-          if ((gps->flag & GP_STROKE_SELECT) == 0) {
-            continue;
+
+          /* apply offset to all points in the stroke */
+          for (int i = 0; i < gps->totpoints; i++) {
+            bGPDspoint *pt = &gps->points[i];
+            add_v3_v3(&pt->x, offset);
           }
 
-          if (use_offset) {
-            float offset[3];
+          changed = true;
+        }
+        else {
+          if (GPENCIL_STROKE_TYPE_BEZIER(gps)) {
+            float inv_diff_mat[4][4];
+            invert_m4_m4_safe(inv_diff_mat, diff_mat);
 
-            /* compute offset from first point of stroke to cursor */
-            /* TODO: Allow using midpoint instead? */
-            sub_v3_v3v3(offset, cursor_global, &gps->points->x);
+            bGPDcurve *gpc = gps->editcurve;
+            for (int i = 0; i < gpc->tot_curve_points; i++) {
+              bGPDcurve_point *cpt = &gpc->curve_points[i];
+              BezTriple *bezt = &cpt->bezt;
+              if ((cpt->flag & GP_CURVE_POINT_SELECT) == 0) {
+                continue;
+              }
 
-            /* apply offset to all points in the stroke */
-            for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
-              add_v3_v3(&pt->x, offset);
+              float cur[3];
+              mul_v3_m4v3(cur, inv_diff_mat, cursor_global);
+
+              /* If the control point is selected, snap it to the cursor and offset the handles
+               * accordingly. */
+              if (bezt->f2 & SELECT) {
+                float offset[3];
+                sub_v3_v3v3(offset, cur, bezt->vec[1]);
+
+                for (int j = 0; j < 3; j++) {
+                  add_v3_v3(bezt->vec[j], offset);
+                }
+              }
+              /* Snap the handles to the cursor. */
+              else {
+                if (bezt->f1 & SELECT) {
+                  copy_v3_v3(bezt->vec[0], cur);
+                }
+                if (bezt->f3 & SELECT) {
+                  copy_v3_v3(bezt->vec[2], cur);
+                }
+              }
+
+              changed = true;
             }
 
-            changed = true;
+            if (changed) {
+              BKE_gpencil_editcurve_recalculate_handles(gps);
+              gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+              BKE_gpencil_stroke_geometry_update(gpd, gps);
+            }
           }
           else {
             /* affect each selected point */
-            for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+            for (int i = 0; i < gps->totpoints; i++) {
+              bGPDspoint *pt = &gps->points[i];
               if (pt->flag & GP_SPOINT_SELECT) {
                 copy_v3_v3(&pt->x, cursor_global);
                 gpencil_apply_parent_point(depsgraph, obact, gpl, pt);



More information about the Bf-blender-cvs mailing list