[Bf-blender-cvs] [fa39bdacf0a] greasepencil-object: GPencil: New convert Curve to Stroke

Antonioya noreply at git.blender.org
Thu Jul 4 22:58:04 CEST 2019


Commit: fa39bdacf0ab4b8346259e3e953e088afa7d97f3
Author: Antonioya
Date:   Thu Jul 4 22:55:14 2019 +0200
Branches: greasepencil-object
https://developer.blender.org/rBfa39bdacf0ab4b8346259e3e953e088afa7d97f3

GPencil: New convert Curve to Stroke

New operator to convert any curve to grease pencil stroke.

The conversion works as a new option for Convert To operator.

Added a new parameter for selecting the color of the stroke.

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

M	source/blender/blenkernel/BKE_gpencil.h
M	source/blender/blenkernel/intern/gpencil.c
M	source/blender/editors/object/object_add.c

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

diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 742546680a4..47c35f2b2f8 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -24,6 +24,7 @@
  * \ingroup bke
  */
 
+struct Scene;
 struct ArrayGpencilModifierData;
 struct BoundBox;
 struct Brush;
@@ -297,6 +298,12 @@ void BKE_gpencil_get_range_selected(struct bGPDlayer *gpl, int *r_initframe, int
 float BKE_gpencil_multiframe_falloff_calc(
     struct bGPDframe *gpf, int actnum, int f_init, int f_end, struct CurveMapping *cur_falloff);
 
+void BKE_gpencil_convert_curve(struct Main *bmain,
+                               const struct Scene *scene,
+                               struct Object *ob_gp,
+                               struct Object *ob_cu,
+                               const bool gpencil_lines);
+
 extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd);
 extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
 
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 058c0d10b8e..6b875507e44 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -48,6 +48,7 @@
 
 #include "BKE_action.h"
 #include "BKE_animsys.h"
+#include "BKE_curve.h"
 #include "BKE_deform.h"
 #include "BKE_gpencil.h"
 #include "BKE_colortools.h"
@@ -57,6 +58,8 @@
 #include "BKE_object.h"
 #include "BKE_material.h"
 
+#include "BLI_math_color.h"
+
 #include "DEG_depsgraph.h"
 
 static CLG_LogRef LOG = {"bke.gpencil"};
@@ -2040,3 +2043,167 @@ bool BKE_gpencil_close_stroke(bGPDstroke *gps)
 
   return true;
 }
+
+/* Helper function to check materials with same color */
+static int gpencil_check_same_material_color(Object *ob_gp, Material *mat_cu, Material *r_mat)
+{
+  Material *ma = NULL;
+  float color_cu[4] = {mat_cu->r, mat_cu->g, mat_cu->b, mat_cu->a};
+  for (int i = 1; i <= ob_gp->totcol; i++) {
+    ma = give_current_material(ob_gp, i);
+    MaterialGPencilStyle *gp_style = ma->gp_style;
+    if (equals_v4v4(color_cu, gp_style->fill_rgba)) {
+      r_mat = ma;
+      return i - 1;
+    }
+  }
+
+  r_mat = NULL;
+  return -1;
+}
+
+/* Helper function to create new stroke section */
+static void gpencil_add_new_points(bGPDstroke *gps, float *coord_array, int init, int totpoints)
+{
+  for (int i = 0; i < totpoints; i++) {
+    bGPDspoint *pt = &gps->points[i + init];
+    copy_v3_v3(&pt->x, &coord_array[3 * i]);
+    pt->pressure = 1.0f;
+    pt->strength = 1.0f;
+  }
+}
+
+/* Convert a curve to grease pencil stroke.
+ *
+ * \param scene: Original scene.
+ * \param ob_gp: Grease pencil object to add strokes.
+ * \param ob_cu: Curve to convert.
+ */
+void BKE_gpencil_convert_curve(
+    Main *bmain, const Scene *scene, Object *ob_gp, Object *ob_cu, const bool gpencil_lines)
+{
+  if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL)) {
+    return;
+  }
+
+  bGPdata *gpd = (bGPdata *)ob_gp->data;
+  Curve *cu = (Curve *)ob_cu->data;
+  Nurb *nu = NULL;
+  bool cyclic = true;
+
+  /* Check if there is an active layer. */
+  bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+  if (gpl == NULL) {
+    gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+  }
+  /* Check if there is an active frame. */
+  bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+  /* Create Stroke. */
+  bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
+  gps->thickness = 1.0f;
+  gps->gradient_f = 1.0f;
+  ARRAY_SET_ITEMS(gps->gradient_s, 1.0f, 1.0f);
+  gps->inittime = 0.0f;
+
+  /* Enable recalculation flag by default. */
+  gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+  gps->flag &= ~GP_STROKE_SELECT;
+  gps->flag |= GP_STROKE_3DSPACE;
+
+  gps->mat_nr = 0;
+  /* Count total points
+   * The total of points must consider that last point of each segment is equal to the first
+   * point of next segment.
+   */
+  int totpoints = 0;
+  int segments = 0;
+  for (nu = cu->nurb.first; nu; nu = nu->next) {
+    int resolu = nu->resolu + 1;
+    if (nu->type == CU_BEZIER) {
+      segments = nu->pntsu;
+      if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
+        segments--;
+        cyclic = false;
+      }
+      totpoints += resolu * segments;
+    }
+  }
+  totpoints -= segments - 1;
+  gps->totpoints = totpoints;
+  /* Allocate memory for storage points, but keep empty. */
+  gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+  /* Initialize triangle memory to dummy data. */
+  gps->tot_triangles = 0;
+  gps->triangles = NULL;
+
+  /* Materials */
+  if ((cu->mat) && (*cu->mat)) {
+    Material *mat_cu = *cu->mat;
+    Material *mat_gp = NULL;
+    /* Check if grease pencil has a material with same color.*/
+    int r_idx = gpencil_check_same_material_color(ob_gp, mat_cu, mat_gp);
+    if (r_idx < 0) {
+      mat_gp = BKE_gpencil_object_material_new(bmain, ob_gp, "GPMat", &r_idx);
+      MaterialGPencilStyle *gp_style = mat_gp->gp_style;
+      if (gpencil_lines) {
+        ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
+      }
+      else {
+        linearrgb_to_srgb_v3_v3(gp_style->stroke_rgba, &mat_cu->r);
+        gp_style->stroke_rgba[3] = 1.0f;
+      }
+
+      linearrgb_to_srgb_v3_v3(gp_style->fill_rgba, &mat_cu->r);
+      gp_style->fill_rgba[3] = 1.0f;
+
+      gp_style->flag |= GP_STYLE_FILL_SHOW;
+    }
+    gps->mat_nr = r_idx;
+  }
+
+  /* Add stroke to frame.*/
+  BLI_addtail(&gpf->strokes, gps);
+
+  /* Read all segments of the curve. */
+  int init = 0;
+  for (nu = cu->nurb.first; nu; nu = nu->next) {
+    int resolu = nu->resolu + 1;
+    if (nu->type == CU_BEZIER) {
+      segments = nu->pntsu;
+      if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
+        segments--;
+      }
+      /* Get all interpolated curve points of Beziert */
+      for (int s = 0; s < segments; s++) {
+        int inext = (s + 1) % nu->pntsu;
+        BezTriple *prevbezt = &nu->bezt[s];
+        BezTriple *bezt = &nu->bezt[inext];
+
+        float *coord_array = MEM_callocN(3 * resolu * sizeof(float), __func__);
+
+        for (int j = 0; j < 3; j++) {
+          BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
+                                        prevbezt->vec[2][j],
+                                        bezt->vec[0][j],
+                                        bezt->vec[1][j],
+                                        coord_array + j,
+                                        resolu - 1,
+                                        3 * sizeof(float));
+        }
+        /* Add points to the stroke */
+        gpencil_add_new_points(gps, coord_array, init, resolu);
+        /* Free memory. */
+        MEM_SAFE_FREE(coord_array);
+
+        /* As the last point of segment is the first point of next segment, back one array element
+         * to avoid duplicated points on the same location.
+         */
+        init += resolu - 1;
+      }
+    }
+  }
+  /* Cyclic curve, close stroke. */
+  if (cyclic) {
+    BKE_gpencil_close_stroke(gps);
+  }
+}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index a3e3196bb13..c56f60118f9 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1951,6 +1951,7 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
 static const EnumPropertyItem convert_target_items[] = {
     {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
     {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""},
+    {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve", ""},
     {0, NULL, 0, NULL, NULL},
 };
 
@@ -2069,14 +2070,17 @@ static int convert_exec(bContext *C, wmOperator *op)
   Depsgraph *depsgraph = CTX_data_depsgraph(C);
   Scene *scene = CTX_data_scene(C);
   ViewLayer *view_layer = CTX_data_view_layer(C);
+  View3D *v3d = CTX_wm_view3d(C);
   Base *basen = NULL, *basact = NULL;
   Object *ob1, *obact = CTX_data_active_object(C);
   Curve *cu;
   Nurb *nu;
   MetaBall *mb;
   Mesh *me;
+  Object *gpencil_ob = NULL;
   const short target = RNA_enum_get(op->ptr, "target");
   bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+  const bool gpencil_lines = RNA_boolean_get(op->ptr, "gpencil_lines");
   int a, mballConverted = 0;
 
   /* don't forget multiple users! */
@@ -2314,6 +2318,15 @@ static int convert_exec(bContext *C, wmOperator *op)
         /* meshes doesn't use displist */
         BKE_object_free_curve_cache(newob);
       }
+      else if (target == OB_GPENCIL) {
+        /* Create a new grease pencil object */
+        if (gpencil_ob == NULL) {
+          const float *cur = scene->cursor.location;
+          ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
+          gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits);
+        }
+        BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, gpencil_lines);
+      }
     }
     else if (ob->type == OB_MBALL && target == OB_MESH) {
       Object *baseob;
@@ -2457,6 +2470,11 @@ void OBJECT_OT_convert(wmOperatorType *ot)
                   0,
                   "Keep Original",
                   "Keep original objects instead of replacing them");
+  RNA_def_boolean(ot->srna,
+                  "gpencil_lines",
+                  1,
+                  "GPencil Lines",
+                  "Use black color lines for grease pencil conversion");
 }
 
 /** \} */



More information about the Bf-blender-cvs mailing list