[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