Blender  V3.3
io_gpencil_export.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #ifdef WITH_IO_GPENCIL
9 
10 # include "BLI_path_util.h"
11 # include "BLI_string.h"
12 
13 # include "DNA_gpencil_types.h"
14 # include "DNA_space_types.h"
15 
16 # include "BKE_gpencil.h"
17 # include "BKE_main.h"
18 # include "BKE_report.h"
19 # include "BKE_screen.h"
20 
21 # include "BLT_translation.h"
22 
23 # include "RNA_access.h"
24 # include "RNA_define.h"
25 
26 # include "UI_interface.h"
27 # include "UI_resources.h"
28 
29 # include "WM_api.h"
30 # include "WM_types.h"
31 
32 # include "DEG_depsgraph.h"
33 # include "DEG_depsgraph_query.h"
34 
35 # include "io_gpencil.h"
36 
37 # include "gpencil_io.h"
38 
39 # if defined(WITH_PUGIXML) || defined(WITH_HARU)
40 /* Definition of enum elements to export. */
41 /* Common props for exporting. */
42 static void gpencil_export_common_props_definition(wmOperatorType *ot)
43 {
44  static const EnumPropertyItem select_items[] = {
45  {GP_EXPORT_ACTIVE, "ACTIVE", 0, "Active", "Include only the active object"},
46  {GP_EXPORT_SELECTED, "SELECTED", 0, "Selected", "Include selected objects"},
47  {GP_EXPORT_VISIBLE, "VISIBLE", 0, "Visible", "Include all visible objects"},
48  {0, NULL, 0, NULL, NULL},
49  };
50 
51  RNA_def_boolean(ot->srna, "use_fill", true, "Fill", "Export strokes with fill enabled");
53  "selected_object_type",
54  select_items,
56  "Object",
57  "Which objects to include in the export");
59  "stroke_sample",
60  0.0f,
61  0.0f,
62  100.0f,
63  "Sampling",
64  "Precision of stroke sampling. Low values mean a more precise result, and zero "
65  "disables sampling",
66  0.0f,
67  100.0f);
69  "use_normalized_thickness",
70  false,
71  "Normalize",
72  "Export strokes with constant thickness");
73 }
74 
75 static void set_export_filepath(bContext *C, wmOperator *op, const char *extension)
76 {
77  if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
78  Main *bmain = CTX_data_main(C);
79  char filepath[FILE_MAX];
80 
81  if (BKE_main_blendfile_path(bmain)[0] == '\0') {
82  BLI_strncpy(filepath, "untitled", sizeof(filepath));
83  }
84  else {
85  BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
86  }
87 
88  BLI_path_extension_replace(filepath, sizeof(filepath), extension);
89  RNA_string_set(op->ptr, "filepath", filepath);
90  }
91 }
92 # endif
93 
94 /* <-------- SVG single frame export. --------> */
95 # ifdef WITH_PUGIXML
96 static bool wm_gpencil_export_svg_common_check(bContext *UNUSED(C), wmOperator *op)
97 {
98  char filepath[FILE_MAX];
99  RNA_string_get(op->ptr, "filepath", filepath);
100 
101  if (!BLI_path_extension_check(filepath, ".svg")) {
102  BLI_path_extension_ensure(filepath, FILE_MAX, ".svg");
103  RNA_string_set(op->ptr, "filepath", filepath);
104  return true;
105  }
106 
107  return false;
108 }
109 
110 static int wm_gpencil_export_svg_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
111 {
112  set_export_filepath(C, op, ".svg");
113 
115 
116  return OPERATOR_RUNNING_MODAL;
117 }
118 
119 static int wm_gpencil_export_svg_exec(bContext *C, wmOperator *op)
120 {
123 
124  if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
125  BKE_report(op->reports, RPT_ERROR, "No filename given");
126  return OPERATOR_CANCELLED;
127  }
128 
129  ARegion *region = get_invoke_region(C);
130  if (region == NULL) {
131  BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
132  return OPERATOR_CANCELLED;
133  }
134  View3D *v3d = get_invoke_view3d(C);
135 
136  char filename[FILE_MAX];
137  RNA_string_get(op->ptr, "filepath", filename);
138 
139  const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
140  const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
141  const eGpencilExportSelect select_mode = RNA_enum_get(op->ptr, "selected_object_type");
142 
143  const bool use_clip_camera = RNA_boolean_get(op->ptr, "use_clip_camera");
144 
145  /* Set flags. */
146  int flag = 0;
147  SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
148  SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
149  SET_FLAG_FROM_TEST(flag, use_clip_camera, GP_EXPORT_CLIP_CAMERA);
150 
151  GpencilIOParams params = {.C = C,
152  .region = region,
153  .v3d = v3d,
154  .ob = ob,
156  .frame_start = scene->r.cfra,
157  .frame_end = scene->r.cfra,
158  .frame_cur = scene->r.cfra,
159  .flag = flag,
160  .scale = 1.0f,
161  .select_mode = select_mode,
162  .frame_mode = GP_EXPORT_FRAME_ACTIVE,
163  .stroke_sample = RNA_float_get(op->ptr, "stroke_sample"),
164  .resolution = 1.0f};
165 
166  /* Do export. */
167  WM_cursor_wait(true);
168  const bool done = gpencil_io_export(filename, &params);
169  WM_cursor_wait(false);
170 
171  if (!done) {
172  BKE_report(op->reports, RPT_WARNING, "Unable to export SVG");
173  }
174 
175  return OPERATOR_FINISHED;
176 }
177 
178 static void ui_gpencil_export_svg_settings(uiLayout *layout, PointerRNA *imfptr)
179 {
180  uiLayout *box, *row;
181 
182  uiLayoutSetPropSep(layout, true);
183  uiLayoutSetPropDecorate(layout, false);
184 
185  box = uiLayoutBox(layout);
186 
187  row = uiLayoutRow(box, false);
188  uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
189 
190  row = uiLayoutRow(box, false);
191  uiItemR(row, imfptr, "selected_object_type", 0, NULL, ICON_NONE);
192 
193  box = uiLayoutBox(layout);
194  row = uiLayoutRow(box, false);
195  uiItemL(row, IFACE_("Export Options"), ICON_NONE);
196 
197  uiLayout *col = uiLayoutColumn(box, false);
198  uiItemR(col, imfptr, "stroke_sample", 0, NULL, ICON_NONE);
199  uiItemR(col, imfptr, "use_fill", 0, NULL, ICON_NONE);
200  uiItemR(col, imfptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
201  uiItemR(col, imfptr, "use_clip_camera", 0, NULL, ICON_NONE);
202 }
203 
204 static void wm_gpencil_export_svg_draw(bContext *UNUSED(C), wmOperator *op)
205 {
206  ui_gpencil_export_svg_settings(op->layout, op->ptr);
207 }
208 
209 static bool wm_gpencil_export_svg_poll(bContext *C)
210 {
212  return false;
213  }
214 
215  return true;
216 }
217 
218 void WM_OT_gpencil_export_svg(wmOperatorType *ot)
219 {
220  ot->name = "Export to SVG";
221  ot->description = "Export grease pencil to SVG";
222  ot->idname = "WM_OT_gpencil_export_svg";
223 
224  ot->invoke = wm_gpencil_export_svg_invoke;
225  ot->exec = wm_gpencil_export_svg_exec;
226  ot->poll = wm_gpencil_export_svg_poll;
227  ot->ui = wm_gpencil_export_svg_draw;
228  ot->check = wm_gpencil_export_svg_common_check;
229 
232  FILE_BLENDER,
233  FILE_SAVE,
237 
238  gpencil_export_common_props_definition(ot);
239 
241  "use_clip_camera",
242  false,
243  "Clip Camera",
244  "Clip drawings to camera size when export in camera view");
245 }
246 # endif
247 
248 /* <-------- PDF single frame export. --------> */
249 # ifdef WITH_HARU
250 static bool wm_gpencil_export_pdf_common_check(bContext *UNUSED(C), wmOperator *op)
251 {
252 
253  char filepath[FILE_MAX];
254  RNA_string_get(op->ptr, "filepath", filepath);
255 
256  if (!BLI_path_extension_check(filepath, ".pdf")) {
257  BLI_path_extension_ensure(filepath, FILE_MAX, ".pdf");
258  RNA_string_set(op->ptr, "filepath", filepath);
259  return true;
260  }
261 
262  return false;
263 }
264 
265 static int wm_gpencil_export_pdf_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
266 {
267  set_export_filepath(C, op, ".pdf");
268 
270 
271  return OPERATOR_RUNNING_MODAL;
272 }
273 
274 static int wm_gpencil_export_pdf_exec(bContext *C, wmOperator *op)
275 {
278 
279  if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
280  BKE_report(op->reports, RPT_ERROR, "No filename given");
281  return OPERATOR_CANCELLED;
282  }
283 
284  ARegion *region = get_invoke_region(C);
285  if (region == NULL) {
286  BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
287  return OPERATOR_CANCELLED;
288  }
289  View3D *v3d = get_invoke_view3d(C);
290 
291  char filename[FILE_MAX];
292  RNA_string_get(op->ptr, "filepath", filename);
293 
294  const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
295  const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
296  const short select_mode = RNA_enum_get(op->ptr, "selected_object_type");
297  const short frame_mode = RNA_enum_get(op->ptr, "frame_mode");
298 
299  /* Set flags. */
300  int flag = 0;
301  SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
302  SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
303 
304  GpencilIOParams params = {.C = C,
305  .region = region,
306  .v3d = v3d,
307  .ob = ob,
309  .frame_start = scene->r.sfra,
310  .frame_end = scene->r.efra,
311  .frame_cur = scene->r.cfra,
312  .flag = flag,
313  .scale = 1.0f,
314  .select_mode = select_mode,
315  .frame_mode = frame_mode,
316  .stroke_sample = RNA_float_get(op->ptr, "stroke_sample"),
317  .resolution = 1.0f};
318 
319  /* Do export. */
320  WM_cursor_wait(true);
321  const bool done = gpencil_io_export(filename, &params);
322  WM_cursor_wait(false);
323 
324  if (!done) {
325  BKE_report(op->reports, RPT_WARNING, "Unable to export PDF");
326  }
327 
328  return OPERATOR_FINISHED;
329 }
330 
331 static void ui_gpencil_export_pdf_settings(uiLayout *layout, PointerRNA *imfptr)
332 {
333  uiLayout *box, *row, *col, *sub;
334 
335  uiLayoutSetPropSep(layout, true);
336  uiLayoutSetPropDecorate(layout, false);
337 
338  box = uiLayoutBox(layout);
339 
340  row = uiLayoutRow(box, false);
341  uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
342 
343  row = uiLayoutRow(box, false);
344  uiItemR(row, imfptr, "selected_object_type", 0, NULL, ICON_NONE);
345 
346  box = uiLayoutBox(layout);
347  row = uiLayoutRow(box, false);
348  uiItemL(row, IFACE_("Export Options"), ICON_NONE);
349 
350  col = uiLayoutColumn(box, false);
351  sub = uiLayoutColumn(col, true);
352  uiItemR(sub, imfptr, "frame_mode", 0, IFACE_("Frame"), ICON_NONE);
353 
354  uiLayoutSetPropSep(box, true);
355 
356  sub = uiLayoutColumn(col, true);
357  uiItemR(sub, imfptr, "stroke_sample", 0, NULL, ICON_NONE);
358  uiItemR(sub, imfptr, "use_fill", 0, NULL, ICON_NONE);
359  uiItemR(sub, imfptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
360 }
361 
362 static void wm_gpencil_export_pdf_draw(bContext *UNUSED(C), wmOperator *op)
363 {
364  ui_gpencil_export_pdf_settings(op->layout, op->ptr);
365 }
366 
367 static bool wm_gpencil_export_pdf_poll(bContext *C)
368 {
370  return false;
371  }
372 
373  return true;
374 }
375 
376 void WM_OT_gpencil_export_pdf(wmOperatorType *ot)
377 {
378  ot->name = "Export to PDF";
379  ot->description = "Export grease pencil to PDF";
380  ot->idname = "WM_OT_gpencil_export_pdf";
381 
382  ot->invoke = wm_gpencil_export_pdf_invoke;
383  ot->exec = wm_gpencil_export_pdf_exec;
384  ot->poll = wm_gpencil_export_pdf_poll;
385  ot->ui = wm_gpencil_export_pdf_draw;
386  ot->check = wm_gpencil_export_pdf_common_check;
387 
390  FILE_BLENDER,
391  FILE_SAVE,
395 
396  static const EnumPropertyItem gpencil_export_frame_items[] = {
397  {GP_EXPORT_FRAME_ACTIVE, "ACTIVE", 0, "Active", "Include only active frame"},
398  {GP_EXPORT_FRAME_SELECTED, "SELECTED", 0, "Selected", "Include selected frames"},
399  {GP_EXPORT_FRAME_SCENE, "SCENE", 0, "Scene", "Include all scene frames"},
400  {0, NULL, 0, NULL, NULL},
401  };
402 
403  gpencil_export_common_props_definition(ot);
404  ot->prop = RNA_def_enum(ot->srna,
405  "frame_mode",
406  gpencil_export_frame_items,
408  "Frames",
409  "Which frames to include in the export");
410 }
411 # endif /* WITH_HARU */
412 
413 #endif /* WITH_IO_GPENCIL */
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
@ CTX_MODE_OBJECT
Definition: BKE_context.h:118
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
Definition: context.c:1228
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define FILE_MAX
bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1420
bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1393
bool BLI_path_extension_check(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1299
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define IFACE_(msgid)
@ FILE_SORT_DEFAULT
@ FILE_BLENDER
@ FILE_TYPE_OBJECT_IO
@ FILE_TYPE_FOLDER
@ FILE_DEFAULTDISPLAY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemL(uiLayout *layout, const char *name, int icon)
uiLayout * uiLayoutBox(uiLayout *layout)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
@ WM_FILESEL_SHOW_PROPS
Definition: WM_api.h:758
@ WM_FILESEL_FILEPATH
Definition: WM_api.h:755
@ FILE_SAVE
Definition: WM_api.h:765
Scene scene
eGpencilExportSelect
Definition: gpencil_io.h:61
@ GP_EXPORT_SELECTED
Definition: gpencil_io.h:63
@ GP_EXPORT_ACTIVE
Definition: gpencil_io.h:62
@ GP_EXPORT_VISIBLE
Definition: gpencil_io.h:64
@ GP_EXPORT_FRAME_SELECTED
Definition: gpencil_io.h:70
@ GP_EXPORT_FRAME_ACTIVE
Definition: gpencil_io.h:69
@ GP_EXPORT_FRAME_SCENE
Definition: gpencil_io.h:71
@ GP_EXPORT_TO_SVG
Definition: gpencil_io.h:53
@ GP_EXPORT_TO_PDF
Definition: gpencil_io.h:54
bool gpencil_io_export(const char *filepath, struct GpencilIOParams *iparams)
@ GP_EXPORT_NORM_THICKNESS
Definition: gpencil_io.h:47
@ GP_EXPORT_CLIP_CAMERA
Definition: gpencil_io.h:49
@ GP_EXPORT_FILL
Definition: gpencil_io.h:45
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
struct View3D * get_invoke_view3d(struct bContext *C)
struct ARegion * get_invoke_region(struct bContext *C)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
Definition: rna_access.c:5289
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
Definition: BKE_main.h:121
struct RenderData r
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
void(* ui)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:954
bool(* check)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:911
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
void WM_cursor_wait(bool val)
Definition: wm_cursors.c:209
void WM_event_add_fileselect(bContext *C, wmOperator *op)
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)