[Bf-blender-cvs] [e2e3ff6fc30] temp-gpencil-io: GPencil: New modules for Import and Export

Antonio Vazquez noreply at git.blender.org
Tue Jan 19 17:37:23 CET 2021


Commit: e2e3ff6fc300e455583a4d1df091d7c4939839cb
Author: Antonio Vazquez
Date:   Mon Jan 18 16:07:47 2021 +0100
Branches: temp-gpencil-io
https://developer.blender.org/rBe2e3ff6fc300e455583a4d1df091d7c4939839cb

GPencil: New modules for Import and Export

Inlude:

* Export SVG
* Export PDF

* Import SVG

Requires libharu and pugixml.

For importing SVG, the NanoSVG lib is used, but this does not require installation (just a .h file embedded in the project  folder)

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

M	build_files/cmake/platform/platform_win32.cmake
M	release/scripts/startup/bl_ui/space_topbar.py
M	source/blender/blenkernel/BKE_gpencil_geom.h
M	source/blender/blenkernel/intern/gpencil_geom.c
M	source/blender/editors/gpencil/gpencil_utils.c
M	source/blender/editors/include/ED_gpencil.h
M	source/blender/editors/io/CMakeLists.txt
A	source/blender/editors/io/io_gpencil.h
A	source/blender/editors/io/io_gpencil_export.c
A	source/blender/editors/io/io_gpencil_import.c
A	source/blender/editors/io/io_gpencil_utils.c
M	source/blender/editors/io/io_ops.c
M	source/blender/editors/space_file/filelist.c
M	source/blender/io/CMakeLists.txt
A	source/blender/io/gpencil/CMakeLists.txt
A	source/blender/io/gpencil/gpencil_io.h
A	source/blender/io/gpencil/intern/gpencil_io_base.cc
A	source/blender/io/gpencil/intern/gpencil_io_base.h
A	source/blender/io/gpencil/intern/gpencil_io_capi.cc
A	source/blender/io/gpencil/intern/gpencil_io_export_base.cc
A	source/blender/io/gpencil/intern/gpencil_io_export_base.h
A	source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
A	source/blender/io/gpencil/intern/gpencil_io_export_pdf.h
A	source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
A	source/blender/io/gpencil/intern/gpencil_io_export_svg.h
A	source/blender/io/gpencil/intern/gpencil_io_import_base.cc
A	source/blender/io/gpencil/intern/gpencil_io_import_base.h
A	source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
A	source/blender/io/gpencil/intern/gpencil_io_import_svg.h
A	source/blender/io/gpencil/nanosvg/nanosvg.h

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

diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 016ae58fde4..83ab4a0262e 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -800,3 +800,6 @@ if(WITH_POTRACE)
   set(POTRACE_LIBRARIES ${LIBDIR}/potrace/lib/potrace.lib)
   set(POTRACE_FOUND On)
 endif()
+
+set(LIBHARU_INCLUDE_DIR ${LIBDIR}/libharu/include)
+set(LIBHARU_LIBRARIES ${LIBDIR}/libharu/lib/libhpdfsd.lib)
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index a7e28c38b9e..fa499453c14 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -442,6 +442,27 @@ class TOPBAR_MT_file_import(Menu):
         if bpy.app.build_options.alembic:
             self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
 
+        self.layout.menu("TOPBAR_MT_file_gpencil_import")
+
+
+class TOPBAR_MT_file_gpencil_import(Menu):
+    bl_idname = "TOPBAR_MT_file_gpencil_import"
+    bl_label = "Grease Pencil"
+    bl_owner_use_filter = False
+
+    def draw(self, context):
+        self.layout.operator("wm.gpencil_import_svg", text="Scalable Vector Graphics (.svg)")
+
+
+class TOPBAR_MT_file_gpencil_export(Menu):
+    bl_idname = "TOPBAR_MT_file_gpencil_export"
+    bl_label = "Grease Pencil"
+    bl_owner_use_filter = False
+
+    def draw(self, context):
+        self.layout.operator("wm.gpencil_export_svg", text="Scalable Vector Graphics (.svg)")
+        self.layout.operator("wm.gpencil_export_pdf", text="Portable Document Format (.pdf)")
+
 
 class TOPBAR_MT_file_export(Menu):
     bl_idname = "TOPBAR_MT_file_export"
@@ -458,6 +479,8 @@ class TOPBAR_MT_file_export(Menu):
             self.layout.operator(
                 "wm.usd_export", text="Universal Scene Description (.usd, .usdc, .usda)")
 
+        self.layout.menu("TOPBAR_MT_file_gpencil_export")
+
 
 class TOPBAR_MT_file_external_data(Menu):
     bl_label = "External Data"
@@ -816,7 +839,9 @@ classes = (
     TOPBAR_MT_file_recover,
     TOPBAR_MT_file_defaults,
     TOPBAR_MT_templates_more,
+    TOPBAR_MT_file_gpencil_import,
     TOPBAR_MT_file_import,
+    TOPBAR_MT_file_gpencil_export,
     TOPBAR_MT_file_export,
     TOPBAR_MT_file_external_data,
     TOPBAR_MT_file_cleanup,
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index 1c86df73d3c..2eb5315ba47 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -27,10 +27,13 @@
 extern "C" {
 #endif
 
+struct ARegion;
+struct bContext;
 struct BoundBox;
 struct Depsgraph;
 struct Main;
 struct Object;
+struct RegionView3D;
 struct Scene;
 struct bGPDcurve;
 struct bGPDframe;
@@ -168,6 +171,24 @@ void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd,
                                           const uint32_t target_number,
                                           const bool select);
 
+void BKE_gpencil_stroke_to_view_space(struct RegionView3D *rv3d,
+                                      struct bGPDstroke *gps,
+                                      float diff_mat[4][4]);
+void BKE_gpencil_stroke_from_view_space(struct RegionView3D *rv3d,
+                                        struct bGPDstroke *gps,
+                                        float diff_mat[4][4]);
+struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
+                                                          struct bGPdata *gpd,
+                                                          const struct bGPDlayer *gpl,
+                                                          struct bGPDstroke *gps,
+                                                          int subdivisions,
+                                                          float diff_mat[4][4]);
+struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view_2d(struct ARegion *region,
+                                                             const struct bGPdata *gpd,
+                                                             const struct bGPDlayer *gpl,
+                                                             struct bGPDstroke *gps,
+                                                             int subdivisions,
+                                                             float diff_mat[4][4]);
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c
index 981f5d50353..77a205e622c 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.c
@@ -46,9 +46,11 @@
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
 
 #include "BLT_translation.h"
 
+#include "BKE_context.h"
 #include "BKE_deform.h"
 #include "BKE_gpencil.h"
 #include "BKE_gpencil_curve.h"
@@ -3419,4 +3421,602 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
   BKE_gpencil_stroke_geometry_update(gpd, gps);
 }
 
+/**
+ * Stroke to view space
+ * Transforms a stroke to view space. This allows for manipulations in 2D but also easy conversion
+ * back to 3D.
+ * Note: also takes care of parent space transform
+ */
+void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d, bGPDstroke *gps, float diff_mat[4][4])
+{
+  float tmp[3];
+
+  for (int i = 0; i < gps->totpoints; i++) {
+    bGPDspoint *pt = &gps->points[i];
+    /* point to parent space */
+    mul_v3_m4v3(tmp, diff_mat, &pt->x);
+    /* point to view space */
+    mul_m4_v3(rv3d->viewmat, tmp);
+    copy_v3_v3(&pt->x, tmp);
+  }
+}
+
+/**
+ * Stroke from view space
+ * Transforms a stroke from view space back to world space. Inverse of
+ * BKE_gpencil_stroke_to_view_space
+ * Note: also takes care of parent space transform
+ */
+void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d, bGPDstroke *gps, float diff_mat[4][4])
+{
+  float tmp[3];
+  float inverse_diff_mat[4][4];
+  invert_m4_m4(inverse_diff_mat, diff_mat);
+
+  for (int i = 0; i < gps->totpoints; i++) {
+    bGPDspoint *pt = &gps->points[i];
+    mul_v3_m4v3(tmp, rv3d->viewinv, &pt->x);
+    mul_m4_v3(inverse_diff_mat, tmp);
+    copy_v3_v3(&pt->x, tmp);
+  }
+}
+
+/* ----------------------------------------------------------------------------- */
+/* Stroke to perimeter */
+
+typedef struct tPerimeterPoint {
+  struct tPerimeterPoint *next, *prev;
+  float x, y, z;
+  bool is_left;
+} tPerimeterPoint;
+
+static tPerimeterPoint *new_perimeter_point(const float pt[3], bool is_left)
+{
+  tPerimeterPoint *new_pt = MEM_callocN(sizeof(tPerimeterPoint), __func__);
+  copy_v3_v3(&new_pt->x, pt);
+  new_pt->is_left = is_left;
+  return new_pt;
+}
+
+static int generate_arc_from_point_to_point(ListBase *list,
+                                            tPerimeterPoint *from,
+                                            tPerimeterPoint *to,
+                                            float center_pt[3],
+                                            int subdivisions,
+                                            bool clockwise,
+                                            bool is_left)
+{
+  float vec_from[2];
+  float vec_to[2];
+  sub_v2_v2v2(vec_from, &from->x, center_pt);
+  sub_v2_v2v2(vec_to, &to->x, center_pt);
+  if (is_zero_v2(vec_from) || is_zero_v2(vec_to)) {
+    return 0;
+  }
+
+  float dot = dot_v2v2(vec_from, vec_to);
+  float det = cross_v2v2(vec_from, vec_to);
+  float angle = clockwise ? M_PI - atan2f(-det, -dot) : atan2f(-det, -dot) + M_PI;
+
+  /* number of points is 2^(n+1) + 1 on half a circle (n=subdivisions)
+   * so we multiply by (angle / pi) to get the right amount of
+   * points to insert */
+  int num_points = (int)(((1 << (subdivisions + 1)) - 1) * (angle / M_PI));
+  if (num_points > 0) {
+    float angle_incr = angle / (float)num_points;
+
+    float vec_p[3];
+    float vec_t[3];
+    float tmp_angle;
+    tPerimeterPoint *last_point;
+    if (clockwise) {
+      last_point = to;
+      copy_v3_v3(vec_t, vec_to);
+    }
+    else {
+      last_point = from;
+      copy_v3_v3(vec_t, vec_from);
+    }
+
+    for (int i = 0; i < num_points - 1; i++) {
+      tmp_angle = (i + 1) * angle_incr;
+
+      rotate_v2_v2fl(vec_p, vec_t, tmp_angle);
+      add_v2_v2(vec_p, center_pt);
+      vec_p[2] = center_pt[2];
+
+      tPerimeterPoint *new_point = new_perimeter_point(vec_p, is_left);
+      if (clockwise) {
+        BLI_insertlinkbefore(list, last_point, new_point);
+      }
+      else {
+        BLI_insertlinkafter(list, last_point, new_point);
+      }
+
+      last_point = new_point;
+    }
+
+    return num_points - 1;
+  }
+
+  return 0;
+}
+
+static int generate_semi_circle_from_point_to_point(
+    ListBase *list, tPerimeterPoint *from, tPerimeterPoint *to, int subdivisions, bool is_left)
+{
+  int num_points = (1 << (subdivisions + 1)) + 1;
+  float center_pt[3];
+  interp_v3_v3v3(center_pt, &from->x, &to->x, 0.5f);
+
+  float vec_center[2];
+  sub_v2_v2v2(vec_center, &from->x, center_pt);
+  if (is_zero_v2(vec_center)) {
+    return 0;
+  }
+
+  float vec_p[3];  // temp vector to do the vector math
+  float angle_incr = M_PI / ((float)num_points - 1);
+
+  tPerimeterPoint *last_point = from;
+  for (int i = 1; i < num_points; i++) {
+    float angle = i * angle_incr;
+
+    /* rotate vector around point to get perimeter points */
+    rotate_v2_v2fl(vec_p, vec_center, angle);
+    add_v2_v2(vec_p, center_pt);
+    vec_p[2] = center_pt[2];
+
+    tPerimeterPoint *new_point = new_perimeter_point(vec_p, is_left);
+    BLI_insertlinkafter(list, last_point, new_point);
+
+    last_point = new_point;
+  }
+
+  return num_points - 1;
+}
+
+static int generate_perimeter_cap(const float point[4],
+                                  const float other_point[4],
+                                  float radius,
+                                  ListBase *list,
+                                  int subdivisions,
+                                  short cap_type,
+                                  bool is_left)
+{
+  float cap_vec[2];
+  sub_v

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list