[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