Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_gpencil_curve.h47
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h8
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/gpencil_curve.c449
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.c404
-rw-r--r--source/blender/editors/object/object_add.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
7 files changed, 500 insertions, 414 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h
new file mode 100644
index 00000000000..cf6f9074bda
--- /dev/null
+++ b/source/blender/blenkernel/BKE_gpencil_curve.h
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ */
+
+#ifndef __BKE_GPENCIL_CURVE_H__
+#define __BKE_GPENCIL_CURVE_H__
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Main;
+struct Object;
+struct Scene;
+
+void BKE_gpencil_convert_curve(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob_gp,
+ struct Object *ob_cu,
+ const bool gpencil_lines,
+ const bool use_collections,
+ const bool only_stroke);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_GPENCIL_CURVE_H__ */
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index 8c52e6d458b..b26016aa26c 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -98,14 +98,6 @@ bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, const float dist);
float BKE_gpencil_stroke_length(const struct bGPDstroke *gps, bool use_3d);
-void BKE_gpencil_convert_curve(struct Main *bmain,
- struct Scene *scene,
- struct Object *ob_gp,
- struct Object *ob_cu,
- const bool gpencil_lines,
- const bool use_collections,
- const bool only_stroke);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 07c7767f348..9716e5f5d3f 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -122,6 +122,7 @@ set(SRC
intern/font.c
intern/freestyle.c
intern/gpencil.c
+ intern/gpencil_curve.c
intern/gpencil_geom.c
intern/gpencil_modifier.c
intern/hair.c
@@ -308,6 +309,7 @@ set(SRC
BKE_freestyle.h
BKE_global.h
BKE_gpencil.h
+ BKE_gpencil_curve.h
BKE_gpencil_geom.h
BKE_gpencil_modifier.h
BKE_hair.h
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
new file mode 100644
index 00000000000..99fbe318b74
--- /dev/null
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -0,0 +1,449 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "CLG_log.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math_vector.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "BKE_collection.h"
+#include "BKE_curve.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+
+#include "DEG_depsgraph_query.h"
+
+/* Helper: Check materials with same color. */
+static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat)
+{
+ Material *ma = NULL;
+ float color_cu[4];
+ linearrgb_to_srgb_v3_v3(color_cu, color);
+ float hsv1[4];
+ rgb_to_hsv_v(color_cu, hsv1);
+ hsv1[3] = color[3];
+
+ for (int i = 1; i <= ob_gp->totcol; i++) {
+ ma = BKE_object_material_get(ob_gp, i);
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ /* Check color with small tolerance (better in HSV). */
+ float hsv2[4];
+ rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
+ hsv2[3] = gp_style->fill_rgba[3];
+ if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) &&
+ (compare_v4v4(hsv1, hsv2, 0.01f))) {
+ *r_mat = ma;
+ return i - 1;
+ }
+ }
+
+ *r_mat = NULL;
+ return -1;
+}
+
+/* Helper: Add gpencil material using curve material as base. */
+static Material *gpencil_add_from_curve_material(Main *bmain,
+ Object *ob_gp,
+ const float cu_color[4],
+ const bool gpencil_lines,
+ const bool fill,
+ int *r_idx)
+{
+ Material *mat_gp = BKE_gpencil_object_material_new(
+ bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx);
+ MaterialGPencilStyle *gp_style = mat_gp->gp_style;
+
+ /* Stroke color. */
+ if (gpencil_lines) {
+ ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ }
+ else {
+ linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color);
+ gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ }
+
+ /* Fill color. */
+ linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color);
+ /* Fill is false if the original curve hasn't material assigned, so enable it. */
+ if (fill) {
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ }
+
+ /* Check at least one is enabled. */
+ if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) &&
+ ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ }
+
+ return mat_gp;
+}
+
+/* Helper: Create new stroke section. */
+static void gpencil_add_new_points(bGPDstroke *gps,
+ float *coord_array,
+ float pressure,
+ int init,
+ int totpoints,
+ const float init_co[3],
+ bool last)
+{
+ for (int i = 0; i < totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i + init];
+ copy_v3_v3(&pt->x, &coord_array[3 * i]);
+ /* Be sure the last point is not on top of the first point of the curve or
+ * the close of the stroke will produce glitches. */
+ if ((last) && (i > 0) && (i == totpoints - 1)) {
+ float dist = len_v3v3(init_co, &pt->x);
+ if (dist < 0.1f) {
+ /* Interpolate between previous point and current to back slightly. */
+ bGPDspoint *pt_prev = &gps->points[i + init - 1];
+ interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f);
+ }
+ }
+
+ pt->pressure = pressure;
+ pt->strength = 1.0f;
+ }
+}
+
+/* Helper: Get the first collection that includes the object. */
+static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
+{
+ Collection *mycol = NULL;
+ FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ if ((mycol == NULL) && (cob->ob == ob)) {
+ mycol = collection;
+ }
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
+ return mycol;
+}
+
+/* Helper: Convert one spline to grease pencil stroke. */
+static void gpencil_convert_spline(Main *bmain,
+ Object *ob_gp,
+ Object *ob_cu,
+ const bool gpencil_lines,
+ const bool only_stroke,
+ bGPDframe *gpf,
+ Nurb *nu)
+{
+ Curve *cu = (Curve *)ob_cu->data;
+ bool cyclic = true;
+
+ /* Create Stroke. */
+ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
+ gps->thickness = 10.0f;
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = 1.0f;
+ gps->uv_scale = 1.0f;
+
+ ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f);
+ ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND);
+ gps->inittime = 0.0f;
+
+ 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;
+ int resolu = nu->resolu + 1;
+ segments = nu->pntsu;
+ if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
+ segments--;
+ cyclic = false;
+ }
+ totpoints = (resolu * segments) - (segments - 1);
+
+ /* Materials
+ * Notice: The color of the material is the color of viewport and not the final shader color.
+ */
+ Material *mat_gp = NULL;
+ bool fill = true;
+ /* Check if grease pencil has a material with same color.*/
+ float color[4];
+ if ((cu->mat) && (*cu->mat)) {
+ Material *mat_cu = *cu->mat;
+ copy_v4_v4(color, &mat_cu->r);
+ }
+ else {
+ /* Gray (unassigned from SVG add-on) */
+ zero_v4(color);
+ add_v3_fl(color, 0.6f);
+ color[3] = 1.0f;
+ fill = false;
+ }
+
+ /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and
+ * there is only one color, the stroke must not be closed, fill to false and use for
+ * stroke the fill color.
+ */
+ bool do_stroke = false;
+ if (ob_cu->totcol == 1) {
+ Material *ma_stroke = BKE_object_material_get(ob_cu, 1);
+ if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) {
+ do_stroke = true;
+ }
+ }
+
+ int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp);
+ if ((ob_cu->totcol > 0) && (r_idx < 0)) {
+ Material *mat_curve = BKE_object_material_get(ob_cu, 1);
+ mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx);
+
+ if ((mat_curve) && (mat_curve->gp_style != NULL)) {
+ MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style;
+ MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style;
+
+ copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba);
+ gp_style_gp->fill_style = gp_style_cur->fill_style;
+ gp_style_gp->mix_factor = gp_style_cur->mix_factor;
+ }
+
+ /* If object has more than 1 material, use second material for stroke color. */
+ if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) {
+ mat_curve = BKE_object_material_get(ob_cu, 2);
+ if (mat_curve) {
+ linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
+ mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
+ }
+ }
+ else if ((only_stroke) || (do_stroke)) {
+ /* Also use the first color if the fill is none for stroke color. */
+ if (ob_cu->totcol > 0) {
+ mat_curve = BKE_object_material_get(ob_cu, 1);
+ if (mat_curve) {
+ copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
+ mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
+ /* Set fill and stroke depending of curve type (3D or 2D). */
+ if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
+ mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
+ }
+ else {
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ }
+ }
+ }
+ }
+ }
+ CLAMP_MIN(r_idx, 0);
+
+ /* Assign material index to stroke. */
+ gps->mat_nr = r_idx;
+
+ /* Add stroke to frame.*/
+ BLI_addtail(&gpf->strokes, gps);
+
+ float *coord_array = NULL;
+ float init_co[3];
+
+ switch (nu->type) {
+ case CU_POLY: {
+ /* Allocate memory for storage points. */
+ gps->totpoints = nu->pntsu;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ /* Increase thickness for this type. */
+ gps->thickness = 10.0f;
+
+ /* Get all curve points */
+ for (int s = 0; s < gps->totpoints; s++) {
+ BPoint *bp = &nu->bp[s];
+ bGPDspoint *pt = &gps->points[s];
+ copy_v3_v3(&pt->x, bp->vec);
+ pt->pressure = bp->radius;
+ pt->strength = 1.0f;
+ }
+ break;
+ }
+ case CU_BEZIER: {
+ /* Allocate memory for storage points. */
+ gps->totpoints = totpoints;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+
+ int init = 0;
+ resolu = nu->resolu + 1;
+ 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];
+ bool last = (bool)(s == segments - 1);
+
+ coord_array = MEM_callocN((size_t)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));
+ }
+ /* Save first point coordinates. */
+ if (s == 0) {
+ copy_v3_v3(init_co, &coord_array[0]);
+ }
+ /* Add points to the stroke */
+ gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last);
+ /* 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;
+ }
+ break;
+ }
+ case CU_NURBS: {
+ if (nu->pntsv == 1) {
+
+ int nurb_points;
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ resolu++;
+ nurb_points = nu->pntsu * resolu;
+ }
+ else {
+ nurb_points = (nu->pntsu - 1) * resolu;
+ }
+ /* Get all curve points. */
+ coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__);
+ BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3]));
+
+ /* Allocate memory for storage points. */
+ gps->totpoints = nurb_points - 1;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+
+ /* Add points. */
+ gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false);
+
+ MEM_SAFE_FREE(coord_array);
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ /* Cyclic curve, close stroke. */
+ if ((cyclic) && (!do_stroke)) {
+ BKE_gpencil_stroke_close(gps);
+ }
+
+ /* Recalc fill geometry. */
+ BKE_gpencil_stroke_geometry_update(gps);
+}
+
+/* Convert a curve object to grease pencil stroke.
+ *
+ * \param bmain: Main thread pointer
+ * \param scene: Original scene.
+ * \param ob_gp: Grease pencil object to add strokes.
+ * \param ob_cu: Curve to convert.
+ * \param gpencil_lines: Use lines for strokes.
+ * \param use_collections: Create layers using collection names.
+ * \param only_stroke: The material must be only stroke without fill.
+ */
+void BKE_gpencil_convert_curve(Main *bmain,
+ Scene *scene,
+ Object *ob_gp,
+ Object *ob_cu,
+ const bool gpencil_lines,
+ const bool use_collections,
+ const bool only_stroke)
+{
+ if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
+ return;
+ }
+
+ Curve *cu = (Curve *)ob_cu->data;
+ bGPdata *gpd = (bGPdata *)ob_gp->data;
+ bGPDlayer *gpl = NULL;
+
+ /* If the curve is empty, cancel. */
+ if (cu->nurb.first == NULL) {
+ return;
+ }
+
+ /* Check if there is an active layer. */
+ if (use_collections) {
+ Collection *collection = gpencil_get_parent_collection(scene, ob_cu);
+ if (collection != NULL) {
+ gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2);
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true);
+ }
+ }
+ }
+
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_active_get(gpd);
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ }
+ }
+
+ /* Check if there is an active frame and add if needed. */
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+
+ /* Read all splines of the curve and create a stroke for each. */
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
+ gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu);
+ }
+
+ /* Tag for recalculation */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c
index 413e28c431b..d200e4e3a15 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.c
@@ -35,18 +35,12 @@
#include "BLI_math_vector.h"
#include "BLI_polyfill_2d.h"
-#include "BLT_translation.h"
-
#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
-#include "BKE_collection.h"
-#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
-#include "BKE_main.h"
-#include "BKE_material.h"
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
@@ -1586,404 +1580,6 @@ void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf,
BKE_gpencil_stroke_geometry_update(gps);
}
-/* Helper: Check materials with same color. */
-static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat)
-{
- Material *ma = NULL;
- float color_cu[4];
- linearrgb_to_srgb_v3_v3(color_cu, color);
- float hsv1[4];
- rgb_to_hsv_v(color_cu, hsv1);
- hsv1[3] = color[3];
-
- for (int i = 1; i <= ob_gp->totcol; i++) {
- ma = BKE_object_material_get(ob_gp, i);
- MaterialGPencilStyle *gp_style = ma->gp_style;
- /* Check color with small tolerance (better in HSV). */
- float hsv2[4];
- rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
- hsv2[3] = gp_style->fill_rgba[3];
- if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) &&
- (compare_v4v4(hsv1, hsv2, 0.01f))) {
- *r_mat = ma;
- return i - 1;
- }
- }
-
- *r_mat = NULL;
- return -1;
-}
-
-/* Helper: Add gpencil material using curve material as base. */
-static Material *gpencil_add_from_curve_material(Main *bmain,
- Object *ob_gp,
- const float cu_color[4],
- const bool gpencil_lines,
- const bool fill,
- int *r_idx)
-{
- Material *mat_gp = BKE_gpencil_object_material_new(
- bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx);
- MaterialGPencilStyle *gp_style = mat_gp->gp_style;
-
- /* Stroke color. */
- if (gpencil_lines) {
- ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
- gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
- }
- else {
- linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color);
- gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
- }
-
- /* Fill color. */
- linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color);
- /* Fill is false if the original curve hasn't material assigned, so enable it. */
- if (fill) {
- gp_style->flag |= GP_MATERIAL_FILL_SHOW;
- }
-
- /* Check at least one is enabled. */
- if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) &&
- ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
- gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
- }
-
- return mat_gp;
-}
-
-/* Helper: Create new stroke section. */
-static void gpencil_add_new_points(bGPDstroke *gps,
- float *coord_array,
- float pressure,
- int init,
- int totpoints,
- const float init_co[3],
- bool last)
-{
- for (int i = 0; i < totpoints; i++) {
- bGPDspoint *pt = &gps->points[i + init];
- copy_v3_v3(&pt->x, &coord_array[3 * i]);
- /* Be sure the last point is not on top of the first point of the curve or
- * the close of the stroke will produce glitches. */
- if ((last) && (i > 0) && (i == totpoints - 1)) {
- float dist = len_v3v3(init_co, &pt->x);
- if (dist < 0.1f) {
- /* Interpolate between previous point and current to back slightly. */
- bGPDspoint *pt_prev = &gps->points[i + init - 1];
- interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f);
- }
- }
-
- pt->pressure = pressure;
- pt->strength = 1.0f;
- }
-}
-
-/* Helper: Get the first collection that includes the object. */
-static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
-{
- Collection *mycol = NULL;
- FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- if ((mycol == NULL) && (cob->ob == ob)) {
- mycol = collection;
- }
- }
- }
- FOREACH_SCENE_COLLECTION_END;
-
- return mycol;
-}
-
-/* Helper: Convert one spline to grease pencil stroke. */
-static void gpencil_convert_spline(Main *bmain,
- Object *ob_gp,
- Object *ob_cu,
- const bool gpencil_lines,
- const bool only_stroke,
- bGPDframe *gpf,
- Nurb *nu)
-{
- Curve *cu = (Curve *)ob_cu->data;
- bool cyclic = true;
-
- /* Create Stroke. */
- bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
- gps->thickness = 10.0f;
- gps->fill_opacity_fac = 1.0f;
- gps->hardeness = 1.0f;
- gps->uv_scale = 1.0f;
-
- ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f);
- ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND);
- gps->inittime = 0.0f;
-
- 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;
- int resolu = nu->resolu + 1;
- segments = nu->pntsu;
- if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
- segments--;
- cyclic = false;
- }
- totpoints = (resolu * segments) - (segments - 1);
-
- /* Materials
- * Notice: The color of the material is the color of viewport and not the final shader color.
- */
- Material *mat_gp = NULL;
- bool fill = true;
- /* Check if grease pencil has a material with same color.*/
- float color[4];
- if ((cu->mat) && (*cu->mat)) {
- Material *mat_cu = *cu->mat;
- copy_v4_v4(color, &mat_cu->r);
- }
- else {
- /* Gray (unassigned from SVG add-on) */
- zero_v4(color);
- add_v3_fl(color, 0.6f);
- color[3] = 1.0f;
- fill = false;
- }
-
- /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and
- * there is only one color, the stroke must not be closed, fill to false and use for
- * stroke the fill color.
- */
- bool do_stroke = false;
- if (ob_cu->totcol == 1) {
- Material *ma_stroke = BKE_object_material_get(ob_cu, 1);
- if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) {
- do_stroke = true;
- }
- }
-
- int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp);
- if ((ob_cu->totcol > 0) && (r_idx < 0)) {
- Material *mat_curve = BKE_object_material_get(ob_cu, 1);
- mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx);
-
- if ((mat_curve) && (mat_curve->gp_style != NULL)) {
- MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style;
- MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style;
-
- copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba);
- gp_style_gp->fill_style = gp_style_cur->fill_style;
- gp_style_gp->mix_factor = gp_style_cur->mix_factor;
- }
-
- /* If object has more than 1 material, use second material for stroke color. */
- if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) {
- mat_curve = BKE_object_material_get(ob_cu, 2);
- if (mat_curve) {
- linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
- mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
- }
- }
- else if ((only_stroke) || (do_stroke)) {
- /* Also use the first color if the fill is none for stroke color. */
- if (ob_cu->totcol > 0) {
- mat_curve = BKE_object_material_get(ob_cu, 1);
- if (mat_curve) {
- copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
- mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
- /* Set fill and stroke depending of curve type (3D or 2D). */
- if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
- mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
- mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
- }
- else {
- mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
- mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
- }
- }
- }
- }
- }
- CLAMP_MIN(r_idx, 0);
-
- /* Assign material index to stroke. */
- gps->mat_nr = r_idx;
-
- /* Add stroke to frame.*/
- BLI_addtail(&gpf->strokes, gps);
-
- float *coord_array = NULL;
- float init_co[3];
-
- switch (nu->type) {
- case CU_POLY: {
- /* Allocate memory for storage points. */
- gps->totpoints = nu->pntsu;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
- /* Increase thickness for this type. */
- gps->thickness = 10.0f;
-
- /* Get all curve points */
- for (int s = 0; s < gps->totpoints; s++) {
- BPoint *bp = &nu->bp[s];
- bGPDspoint *pt = &gps->points[s];
- copy_v3_v3(&pt->x, bp->vec);
- pt->pressure = bp->radius;
- pt->strength = 1.0f;
- }
- break;
- }
- case CU_BEZIER: {
- /* Allocate memory for storage points. */
- gps->totpoints = totpoints;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
-
- int init = 0;
- resolu = nu->resolu + 1;
- 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];
- bool last = (bool)(s == segments - 1);
-
- coord_array = MEM_callocN((size_t)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));
- }
- /* Save first point coordinates. */
- if (s == 0) {
- copy_v3_v3(init_co, &coord_array[0]);
- }
- /* Add points to the stroke */
- gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last);
- /* 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;
- }
- break;
- }
- case CU_NURBS: {
- if (nu->pntsv == 1) {
-
- int nurb_points;
- if (nu->flagu & CU_NURB_CYCLIC) {
- resolu++;
- nurb_points = nu->pntsu * resolu;
- }
- else {
- nurb_points = (nu->pntsu - 1) * resolu;
- }
- /* Get all curve points. */
- coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__);
- BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3]));
-
- /* Allocate memory for storage points. */
- gps->totpoints = nurb_points - 1;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
-
- /* Add points. */
- gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false);
-
- MEM_SAFE_FREE(coord_array);
- }
- break;
- }
- default: {
- break;
- }
- }
- /* Cyclic curve, close stroke. */
- if ((cyclic) && (!do_stroke)) {
- BKE_gpencil_stroke_close(gps);
- }
-
- /* Recalc fill geometry. */
- BKE_gpencil_stroke_geometry_update(gps);
-}
-
-/* Convert a curve object to grease pencil stroke.
- *
- * \param bmain: Main thread pointer
- * \param scene: Original scene.
- * \param ob_gp: Grease pencil object to add strokes.
- * \param ob_cu: Curve to convert.
- * \param gpencil_lines: Use lines for strokes.
- * \param use_collections: Create layers using collection names.
- * \param only_stroke: The material must be only stroke without fill.
- */
-void BKE_gpencil_convert_curve(Main *bmain,
- Scene *scene,
- Object *ob_gp,
- Object *ob_cu,
- const bool gpencil_lines,
- const bool use_collections,
- const bool only_stroke)
-{
- if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
- return;
- }
-
- Curve *cu = (Curve *)ob_cu->data;
- bGPdata *gpd = (bGPdata *)ob_gp->data;
- bGPDlayer *gpl = NULL;
-
- /* If the curve is empty, cancel. */
- if (cu->nurb.first == NULL) {
- return;
- }
-
- /* Check if there is an active layer. */
- if (use_collections) {
- Collection *collection = gpencil_get_parent_collection(scene, ob_cu);
- if (collection != NULL) {
- gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2);
- if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true);
- }
- }
- }
-
- if (gpl == NULL) {
- gpl = BKE_gpencil_layer_active_get(gpd);
- if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
- }
- }
-
- /* Check if there is an active frame and add if needed. */
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY);
-
- /* Read all splines of the curve and create a stroke for each. */
- LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
- gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu);
- }
-
- /* Tag for recalculation */
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
-}
-
/* Apply Transforms */
void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
{
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 64abd01983c..bd5ef23948d 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -64,7 +64,7 @@
#include "BKE_duplilist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
-#include "BKE_gpencil_geom.h"
+#include "BKE_gpencil_curve.h"
#include "BKE_hair.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index bc8f6d4e3ae..b26018394b7 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -36,7 +36,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "BKE_gpencil_geom.h"
+#include "BKE_gpencil_curve.h"
#include "BKE_layer.h"
#include "DEG_depsgraph.h"