Blender  V2.93
io_gpencil_export.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BLI_path_util.h"
25 #include "BLI_string.h"
26 
27 #include "DNA_gpencil_types.h"
28 #include "DNA_space_types.h"
29 
30 #include "BKE_gpencil.h"
31 #include "BKE_main.h"
32 #include "BKE_report.h"
33 #include "BKE_screen.h"
34 
35 #include "BLT_translation.h"
36 
37 #include "RNA_access.h"
38 #include "RNA_define.h"
39 
40 #include "UI_interface.h"
41 #include "UI_resources.h"
42 
43 #include "WM_api.h"
44 #include "WM_types.h"
45 
46 #include "DEG_depsgraph.h"
47 #include "DEG_depsgraph_query.h"
48 
49 #include "io_gpencil.h"
50 
51 #include "gpencil_io.h"
52 
53 #if defined(WITH_PUGIXML) || defined(WITH_HARU)
54 /* Definition of enum elements to export. */
55 /* Common props for exporting. */
56 static void gpencil_export_common_props_definition(wmOperatorType *ot)
57 {
58  static const EnumPropertyItem select_items[] = {
59  {GP_EXPORT_ACTIVE, "ACTIVE", 0, "Active", "Include only the active object"},
60  {GP_EXPORT_SELECTED, "SELECTED", 0, "Selected", "Include selected objects"},
61  {GP_EXPORT_VISIBLE, "VISIBLE", 0, "Visible", "Include all visible objects"},
62  {0, NULL, 0, NULL, NULL},
63  };
64 
65  RNA_def_boolean(ot->srna, "use_fill", true, "Fill", "Export strokes with fill enabled");
67  "selected_object_type",
68  select_items,
70  "Object",
71  "Which objects to include in the export");
73  "stroke_sample",
74  0.0f,
75  0.0f,
76  100.0f,
77  "Sampling",
78  "Precision of stroke sampling. Low values mean a more precise result, and zero "
79  "disables sampling",
80  0.0f,
81  100.0f);
83  "use_normalized_thickness",
84  false,
85  "Normalize",
86  "Export strokes with constant thickness");
87 }
88 
89 static void set_export_filepath(bContext *C, wmOperator *op, const char *extension)
90 {
91  if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
92  Main *bmain = CTX_data_main(C);
93  char filepath[FILE_MAX];
94 
95  if (BKE_main_blendfile_path(bmain)[0] == '\0') {
96  BLI_strncpy(filepath, "untitled", sizeof(filepath));
97  }
98  else {
99  BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
100  }
101 
102  BLI_path_extension_replace(filepath, sizeof(filepath), extension);
103  RNA_string_set(op->ptr, "filepath", filepath);
104  }
105 }
106 #endif
107 
108 /* <-------- SVG single frame export. --------> */
109 #ifdef WITH_PUGIXML
110 static bool wm_gpencil_export_svg_common_check(bContext *UNUSED(C), wmOperator *op)
111 {
112  char filepath[FILE_MAX];
113  RNA_string_get(op->ptr, "filepath", filepath);
114 
115  if (!BLI_path_extension_check(filepath, ".svg")) {
116  BLI_path_extension_ensure(filepath, FILE_MAX, ".svg");
117  RNA_string_set(op->ptr, "filepath", filepath);
118  return true;
119  }
120 
121  return false;
122 }
123 
124 static int wm_gpencil_export_svg_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
125 {
126  set_export_filepath(C, op, ".svg");
127 
129 
130  return OPERATOR_RUNNING_MODAL;
131 }
132 
133 static int wm_gpencil_export_svg_exec(bContext *C, wmOperator *op)
134 {
137 
138  if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
139  BKE_report(op->reports, RPT_ERROR, "No filename given");
140  return OPERATOR_CANCELLED;
141  }
142 
143  ARegion *region = get_invoke_region(C);
144  if (region == NULL) {
145  BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
146  return OPERATOR_CANCELLED;
147  }
148  View3D *v3d = get_invoke_view3d(C);
149 
150  char filename[FILE_MAX];
151  RNA_string_get(op->ptr, "filepath", filename);
152 
153  const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
154  const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
155  const eGpencilExportSelect select_mode = RNA_enum_get(op->ptr, "selected_object_type");
156 
157  const bool use_clip_camera = RNA_boolean_get(op->ptr, "use_clip_camera");
158 
159  /* Set flags. */
160  int flag = 0;
161  SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
162  SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
163  SET_FLAG_FROM_TEST(flag, use_clip_camera, GP_EXPORT_CLIP_CAMERA);
164 
165  GpencilIOParams params = {.C = C,
166  .region = region,
167  .v3d = v3d,
168  .ob = ob,
170  .frame_start = CFRA,
171  .frame_end = CFRA,
172  .frame_cur = CFRA,
173  .flag = flag,
174  .scale = 1.0f,
175  .select_mode = select_mode,
176  .frame_mode = GP_EXPORT_FRAME_ACTIVE,
177  .stroke_sample = RNA_float_get(op->ptr, "stroke_sample"),
178  .resolution = 1.0f};
179 
180  /* Do export. */
181  WM_cursor_wait(true);
182  const bool done = gpencil_io_export(filename, &params);
183  WM_cursor_wait(false);
184 
185  if (!done) {
186  BKE_report(op->reports, RPT_WARNING, "Unable to export SVG");
187  }
188 
189  return OPERATOR_FINISHED;
190 }
191 
192 static void ui_gpencil_export_svg_settings(uiLayout *layout, PointerRNA *imfptr)
193 {
194  uiLayout *box, *row;
195 
196  uiLayoutSetPropSep(layout, true);
197  uiLayoutSetPropDecorate(layout, false);
198 
199  box = uiLayoutBox(layout);
200 
201  row = uiLayoutRow(box, false);
202  uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
203 
204  row = uiLayoutRow(box, false);
205  uiItemR(row, imfptr, "selected_object_type", 0, NULL, ICON_NONE);
206 
207  box = uiLayoutBox(layout);
208  row = uiLayoutRow(box, false);
209  uiItemL(row, IFACE_("Export Options"), ICON_NONE);
210 
211  uiLayout *col = uiLayoutColumn(box, false);
212  uiItemR(col, imfptr, "stroke_sample", 0, NULL, ICON_NONE);
213  uiItemR(col, imfptr, "use_fill", 0, NULL, ICON_NONE);
214  uiItemR(col, imfptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
215  uiItemR(col, imfptr, "use_clip_camera", 0, NULL, ICON_NONE);
216 }
217 
218 static void wm_gpencil_export_svg_draw(bContext *C, wmOperator *op)
219 {
221  PointerRNA ptr;
222 
223  RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
224 
225  ui_gpencil_export_svg_settings(op->layout, &ptr);
226 }
227 
228 static bool wm_gpencil_export_svg_poll(bContext *C)
229 {
231  return false;
232  }
233 
234  return true;
235 }
236 
237 void WM_OT_gpencil_export_svg(wmOperatorType *ot)
238 {
239  ot->name = "Export to SVG";
240  ot->description = "Export grease pencil to SVG";
241  ot->idname = "WM_OT_gpencil_export_svg";
242 
243  ot->invoke = wm_gpencil_export_svg_invoke;
244  ot->exec = wm_gpencil_export_svg_exec;
245  ot->poll = wm_gpencil_export_svg_poll;
246  ot->ui = wm_gpencil_export_svg_draw;
247  ot->check = wm_gpencil_export_svg_common_check;
248 
251  FILE_BLENDER,
252  FILE_SAVE,
256 
257  gpencil_export_common_props_definition(ot);
258 
260  "use_clip_camera",
261  false,
262  "Clip Camera",
263  "Clip drawings to camera size when export in camera view");
264 }
265 #endif
266 
267 /* <-------- PDF single frame export. --------> */
268 #ifdef WITH_HARU
269 static bool wm_gpencil_export_pdf_common_check(bContext *UNUSED(C), wmOperator *op)
270 {
271 
272  char filepath[FILE_MAX];
273  RNA_string_get(op->ptr, "filepath", filepath);
274 
275  if (!BLI_path_extension_check(filepath, ".pdf")) {
276  BLI_path_extension_ensure(filepath, FILE_MAX, ".pdf");
277  RNA_string_set(op->ptr, "filepath", filepath);
278  return true;
279  }
280 
281  return false;
282 }
283 
284 static int wm_gpencil_export_pdf_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
285 {
286  set_export_filepath(C, op, ".pdf");
287 
289 
290  return OPERATOR_RUNNING_MODAL;
291 }
292 
293 static int wm_gpencil_export_pdf_exec(bContext *C, wmOperator *op)
294 {
297 
298  if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
299  BKE_report(op->reports, RPT_ERROR, "No filename given");
300  return OPERATOR_CANCELLED;
301  }
302 
303  ARegion *region = get_invoke_region(C);
304  if (region == NULL) {
305  BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
306  return OPERATOR_CANCELLED;
307  }
308  View3D *v3d = get_invoke_view3d(C);
309 
310  char filename[FILE_MAX];
311  RNA_string_get(op->ptr, "filepath", filename);
312 
313  const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
314  const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
315  const short select_mode = RNA_enum_get(op->ptr, "selected_object_type");
316  const short frame_mode = RNA_enum_get(op->ptr, "frame_mode");
317 
318  /* Set flags. */
319  int flag = 0;
320  SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
321  SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
322 
323  GpencilIOParams params = {.C = C,
324  .region = region,
325  .v3d = v3d,
326  .ob = ob,
328  .frame_start = SFRA,
329  .frame_end = EFRA,
330  .frame_cur = CFRA,
331  .flag = flag,
332  .scale = 1.0f,
333  .select_mode = select_mode,
334  .frame_mode = frame_mode,
335  .stroke_sample = RNA_float_get(op->ptr, "stroke_sample"),
336  .resolution = 1.0f};
337 
338  /* Do export. */
339  WM_cursor_wait(true);
340  const bool done = gpencil_io_export(filename, &params);
341  WM_cursor_wait(false);
342 
343  if (!done) {
344  BKE_report(op->reports, RPT_WARNING, "Unable to export PDF");
345  }
346 
347  return OPERATOR_FINISHED;
348 }
349 
350 static void ui_gpencil_export_pdf_settings(uiLayout *layout, PointerRNA *imfptr)
351 {
352  uiLayout *box, *row, *col, *sub;
353 
354  uiLayoutSetPropSep(layout, true);
355  uiLayoutSetPropDecorate(layout, false);
356 
357  box = uiLayoutBox(layout);
358 
359  row = uiLayoutRow(box, false);
360  uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
361 
362  row = uiLayoutRow(box, false);
363  uiItemR(row, imfptr, "selected_object_type", 0, NULL, ICON_NONE);
364 
365  box = uiLayoutBox(layout);
366  row = uiLayoutRow(box, false);
367  uiItemL(row, IFACE_("Export Options"), ICON_NONE);
368 
369  col = uiLayoutColumn(box, false);
370  sub = uiLayoutColumn(col, true);
371  uiItemR(sub, imfptr, "frame_mode", 0, IFACE_("Frame"), ICON_NONE);
372 
373  uiLayoutSetPropSep(box, true);
374 
375  sub = uiLayoutColumn(col, true);
376  uiItemR(sub, imfptr, "stroke_sample", 0, NULL, ICON_NONE);
377  uiItemR(sub, imfptr, "use_fill", 0, NULL, ICON_NONE);
378  uiItemR(sub, imfptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
379 }
380 
381 static void wm_gpencil_export_pdf_draw(bContext *C, wmOperator *op)
382 {
384  PointerRNA ptr;
385 
386  RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
387 
388  ui_gpencil_export_pdf_settings(op->layout, &ptr);
389 }
390 
391 static bool wm_gpencil_export_pdf_poll(bContext *C)
392 {
394  return false;
395  }
396 
397  return true;
398 }
399 
400 void WM_OT_gpencil_export_pdf(wmOperatorType *ot)
401 {
402  ot->name = "Export to PDF";
403  ot->description = "Export grease pencil to PDF";
404  ot->idname = "WM_OT_gpencil_export_pdf";
405 
406  ot->invoke = wm_gpencil_export_pdf_invoke;
407  ot->exec = wm_gpencil_export_pdf_exec;
408  ot->poll = wm_gpencil_export_pdf_poll;
409  ot->ui = wm_gpencil_export_pdf_draw;
410  ot->check = wm_gpencil_export_pdf_common_check;
411 
414  FILE_BLENDER,
415  FILE_SAVE,
419 
420  static const EnumPropertyItem gpencil_export_frame_items[] = {
421  {GP_EXPORT_FRAME_ACTIVE, "ACTIVE", 0, "Active", "Include only active frame"},
422  {GP_EXPORT_FRAME_SELECTED, "SELECTED", 0, "Selected", "Include selected frames"},
423  {0, NULL, 0, NULL, NULL},
424  };
425 
426  gpencil_export_common_props_definition(ot);
427  ot->prop = RNA_def_enum(ot->srna,
428  "frame_mode",
429  gpencil_export_frame_items,
431  "Frames",
432  "Which frames to include in the export");
433 }
434 #endif
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
@ CTX_MODE_OBJECT
Definition: BKE_context.h:128
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
Definition: context.c:1174
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define FILE_MAX
bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1601
bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1571
bool BLI_path_extension_check(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1459
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define IFACE_(msgid)
#define CFRA
#define SFRA
#define EFRA
@ FILE_SORT_ALPHA
@ FILE_BLENDER
@ FILE_TYPE_OBJECT_IO
@ FILE_SAVE
@ FILE_DEFAULTDISPLAY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
#define C
Definition: RandGen.cpp:39
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)
#define WM_FILESEL_SHOW_PROPS
Definition: WM_api.h:540
#define WM_FILESEL_FILEPATH
Definition: WM_api.h:537
Scene scene
eGpencilExportSelect
Definition: gpencil_io.h:75
@ GP_EXPORT_SELECTED
Definition: gpencil_io.h:77
@ GP_EXPORT_ACTIVE
Definition: gpencil_io.h:76
@ GP_EXPORT_VISIBLE
Definition: gpencil_io.h:78
bool gpencil_io_export(const char *filename, struct GpencilIOParams *iparams)
@ GP_EXPORT_FRAME_SELECTED
Definition: gpencil_io.h:84
@ GP_EXPORT_FRAME_ACTIVE
Definition: gpencil_io.h:83
@ GP_EXPORT_TO_SVG
Definition: gpencil_io.h:67
@ GP_EXPORT_TO_PDF
Definition: gpencil_io.h:68
@ GP_EXPORT_NORM_THICKNESS
Definition: gpencil_io.h:61
@ GP_EXPORT_CLIP_CAMERA
Definition: gpencil_io.h:63
@ GP_EXPORT_FILL
Definition: gpencil_io.h:59
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_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:6550
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:6514
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:6685
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
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:3825
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
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:3771
Definition: BKE_main.h:116
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
void(* ui)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:787
bool(* check)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:744
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
IDProperty * properties
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
void WM_cursor_wait(bool val)
Definition: wm_cursors.c:226
void WM_event_add_fileselect(bContext *C, wmOperator *op)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, short action, short flag, short display, short sort)