Blender V4.3
io_ply_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#ifdef WITH_IO_PLY
10
11# include "BKE_context.hh"
12# include "BKE_file_handler.hh"
13# include "BKE_main.hh"
14# include "BKE_report.hh"
15
16# include "BLI_string.h"
17
18# include "WM_api.hh"
19# include "WM_types.hh"
20
21# include "DNA_space_types.h"
22
23# include "ED_fileselect.hh"
24# include "ED_outliner.hh"
25
26# include "RNA_access.hh"
27# include "RNA_define.hh"
28
29# include "BLT_translation.hh"
30
31# include "UI_interface.hh"
32# include "UI_resources.hh"
33
34# include "IO_orientation.hh"
35
36# include "IO_ply.hh"
37# include "io_ply_ops.hh"
38# include "io_utils.hh"
39
40static const EnumPropertyItem ply_vertex_colors_mode[] = {
41 {PLY_VERTEX_COLOR_NONE, "NONE", 0, "None", "Do not import/export color attributes"},
43 "SRGB",
44 0,
45 "sRGB",
46 "Vertex colors in the file are in sRGB color space"},
48 "LINEAR",
49 0,
50 "Linear",
51 "Vertex colors in the file are in linear color space"},
52 {0, nullptr, 0, nullptr, nullptr}};
53
54static int wm_ply_export_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
55{
57
60}
61
62static int wm_ply_export_exec(bContext *C, wmOperator *op)
63{
64 if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
65 BKE_report(op->reports, RPT_ERROR, "No filepath given");
66 return OPERATOR_CANCELLED;
67 }
68 PLYExportParams export_params{};
69 export_params.file_base_for_tests[0] = '\0';
70 RNA_string_get(op->ptr, "filepath", export_params.filepath);
71 export_params.blen_filepath = CTX_data_main(C)->filepath;
72
73 export_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
74 export_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
75 export_params.global_scale = RNA_float_get(op->ptr, "global_scale");
76 export_params.apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
77
78 export_params.export_selected_objects = RNA_boolean_get(op->ptr, "export_selected_objects");
79 export_params.export_uv = RNA_boolean_get(op->ptr, "export_uv");
80 export_params.export_normals = RNA_boolean_get(op->ptr, "export_normals");
81 export_params.vertex_colors = ePLYVertexColorMode(RNA_enum_get(op->ptr, "export_colors"));
82 export_params.export_attributes = RNA_boolean_get(op->ptr, "export_attributes");
83 export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh");
84 export_params.ascii_format = RNA_boolean_get(op->ptr, "ascii_format");
85
86 RNA_string_get(op->ptr, "collection", export_params.collection);
87
88 export_params.reports = op->reports;
89
90 PLY_export(C, &export_params);
91
93}
94
95static void wm_ply_export_draw(bContext *C, wmOperator *op)
96{
97 uiLayout *layout = op->layout;
98 PointerRNA *ptr = op->ptr;
99
100 uiLayoutSetPropSep(layout, true);
101 uiLayoutSetPropDecorate(layout, false);
102
103 if (uiLayout *panel = uiLayoutPanel(C, layout, "PLY_export_general", false, IFACE_("General"))) {
104 uiLayout *col = uiLayoutColumn(panel, false);
105
106 uiLayout *sub = uiLayoutColumnWithHeading(col, false, IFACE_("Format"));
107 uiItemR(sub, ptr, "ascii_format", UI_ITEM_NONE, IFACE_("ASCII"), ICON_NONE);
108
109 /* The Selection only options only make sense when using regular export. */
110 if (CTX_wm_space_file(C)) {
111 sub = uiLayoutColumnWithHeading(col, false, IFACE_("Include"));
112 uiItemR(
113 sub, ptr, "export_selected_objects", UI_ITEM_NONE, IFACE_("Selection Only"), ICON_NONE);
114 }
115
116 uiItemR(col, ptr, "global_scale", UI_ITEM_NONE, nullptr, ICON_NONE);
117 uiItemR(col, ptr, "forward_axis", UI_ITEM_NONE, IFACE_("Forward Axis"), ICON_NONE);
118 uiItemR(col, ptr, "up_axis", UI_ITEM_NONE, IFACE_("Up Axis"), ICON_NONE);
119 }
120
121 if (uiLayout *panel = uiLayoutPanel(C, layout, "PLY_export_geometry", false, IFACE_("Geometry")))
122 {
123 uiLayout *col = uiLayoutColumn(panel, false);
124
125 uiItemR(col, ptr, "export_uv", UI_ITEM_NONE, IFACE_("UV Coordinates"), ICON_NONE);
126 uiItemR(col, ptr, "export_normals", UI_ITEM_NONE, IFACE_("Vertex Normals"), ICON_NONE);
127 uiItemR(col, ptr, "export_attributes", UI_ITEM_NONE, IFACE_("Vertex Attributes"), ICON_NONE);
128 uiItemR(col, ptr, "export_colors", UI_ITEM_NONE, IFACE_("Vertex Colors"), ICON_NONE);
129
130 uiItemR(col,
131 ptr,
132 "export_triangulated_mesh",
134 IFACE_("Triangulated Mesh"),
135 ICON_NONE);
136 uiItemR(col, ptr, "apply_modifiers", UI_ITEM_NONE, IFACE_("Apply Modifiers"), ICON_NONE);
137 }
138}
139
143static bool wm_ply_export_check(bContext * /*C*/, wmOperator *op)
144{
145 char filepath[FILE_MAX];
146 bool changed = false;
147 RNA_string_get(op->ptr, "filepath", filepath);
148
149 if (!BLI_path_extension_check(filepath, ".ply")) {
150 BLI_path_extension_ensure(filepath, FILE_MAX, ".ply");
151 RNA_string_set(op->ptr, "filepath", filepath);
152 changed = true;
153 }
154 return changed;
155}
156
158{
159 PropertyRNA *prop;
160
161 ot->name = "Export PLY";
162 ot->description = "Save the scene to a PLY file";
163 ot->idname = "WM_OT_ply_export";
164
165 ot->invoke = wm_ply_export_invoke;
166 ot->exec = wm_ply_export_exec;
168 ot->ui = wm_ply_export_draw;
169 ot->check = wm_ply_export_check;
170
172
176 FILE_SAVE,
180
181 /* Object transform options. */
182 prop = RNA_def_enum(ot->srna, "forward_axis", io_transform_axis, IO_AXIS_Y, "Forward Axis", "");
184 prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Z, "Up Axis", "");
187 ot->srna,
188 "global_scale",
189 1.0f,
190 0.0001f,
191 10000.0f,
192 "Scale",
193 "Value by which to enlarge or shrink the objects with respect to the world's origin",
194 0.0001f,
195 10000.0f);
196 /* File Writer options. */
198 ot->srna, "apply_modifiers", true, "Apply Modifiers", "Apply modifiers to exported meshes");
200 "export_selected_objects",
201 false,
202 "Export Selected Objects",
203 "Export only selected objects instead of all supported objects");
204 prop = RNA_def_string(ot->srna,
205 "collection",
206 nullptr,
208 "Source Collection",
209 "Export only objects from this collection (and its children)");
211
212 RNA_def_boolean(ot->srna, "export_uv", true, "Export UVs", "");
214 ot->srna,
215 "export_normals",
216 false,
217 "Export Vertex Normals",
218 "Export specific vertex normals if available, export calculated normals otherwise");
220 "export_colors",
221 ply_vertex_colors_mode,
223 "Export Vertex Colors",
224 "Export vertex color attributes");
226 "export_attributes",
227 true,
228 "Export Vertex Attributes",
229 "Export custom vertex attributes");
231 "export_triangulated_mesh",
232 false,
233 "Export Triangulated Mesh",
234 "All ngons with four or more vertices will be triangulated. Meshes in "
235 "the scene will not be affected. Behaves like Triangulate Modifier with "
236 "ngon-method: \"Beauty\", quad-method: \"Shortest Diagonal\", min vertices: 4");
238 "ascii_format",
239 false,
240 "ASCII Format",
241 "Export file in ASCII format, export as binary otherwise");
242
243 /* Only show `.ply` files by default. */
244 prop = RNA_def_string(ot->srna, "filter_glob", "*.ply", 0, "Extension Filter", "");
246}
247
248static int wm_ply_import_exec(bContext *C, wmOperator *op)
249{
251 params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
252 params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
253 params.use_scene_unit = RNA_boolean_get(op->ptr, "use_scene_unit");
254 params.global_scale = RNA_float_get(op->ptr, "global_scale");
255 params.merge_verts = RNA_boolean_get(op->ptr, "merge_verts");
256 params.import_attributes = RNA_boolean_get(op->ptr, "import_attributes");
257 params.vertex_colors = ePLYVertexColorMode(RNA_enum_get(op->ptr, "import_colors"));
258
259 params.reports = op->reports;
260
262
263 if (paths.is_empty()) {
264 BKE_report(op->reports, RPT_ERROR, "No filepath given");
265 return OPERATOR_CANCELLED;
266 }
267 for (const auto &path : paths) {
268 STRNCPY(params.filepath, path.c_str());
269 PLY_import(C, &params);
270 };
271
272 Scene *scene = CTX_data_scene(C);
277
278 return OPERATOR_FINISHED;
279}
280
281static void ui_ply_import_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr)
282{
283 uiLayoutSetPropSep(layout, true);
284 uiLayoutSetPropDecorate(layout, false);
285
286 if (uiLayout *panel = uiLayoutPanel(C, layout, "PLY_import_general", false, IFACE_("General"))) {
287 uiLayout *col = uiLayoutColumn(panel, false);
288 uiItemR(col, ptr, "global_scale", UI_ITEM_NONE, nullptr, ICON_NONE);
289 uiItemR(col, ptr, "use_scene_unit", UI_ITEM_NONE, nullptr, ICON_NONE);
290 uiItemR(col, ptr, "forward_axis", UI_ITEM_NONE, nullptr, ICON_NONE);
291 uiItemR(col, ptr, "up_axis", UI_ITEM_NONE, nullptr, ICON_NONE);
292 }
293
294 if (uiLayout *panel = uiLayoutPanel(C, layout, "PLY_import_options", false, IFACE_("Options"))) {
295 uiLayout *col = uiLayoutColumn(panel, false);
296 uiItemR(col, ptr, "merge_verts", UI_ITEM_NONE, nullptr, ICON_NONE);
297 uiItemR(col, ptr, "import_colors", UI_ITEM_NONE, nullptr, ICON_NONE);
298 }
299}
300
301static void wm_ply_import_draw(bContext *C, wmOperator *op)
302{
303 ui_ply_import_settings(C, op->layout, op->ptr);
304}
305
307{
308 PropertyRNA *prop;
309
310 ot->name = "Import PLY";
311 ot->description = "Import an PLY file as an object";
312 ot->idname = "WM_OT_ply_import";
313
315 ot->exec = wm_ply_import_exec;
316 ot->ui = wm_ply_import_draw;
319
328
329 RNA_def_float(ot->srna, "global_scale", 1.0f, 1e-6f, 1e6f, "Scale", "", 0.001f, 1000.0f);
331 "use_scene_unit",
332 false,
333 "Scene Unit",
334 "Apply current scene's unit (as defined by unit scale) to imported data");
335 prop = RNA_def_enum(ot->srna, "forward_axis", io_transform_axis, IO_AXIS_Y, "Forward Axis", "");
337 prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Z, "Up Axis", "");
339 RNA_def_boolean(ot->srna, "merge_verts", false, "Merge Vertices", "Merges vertices by distance");
341 "import_colors",
342 ply_vertex_colors_mode,
344 "Vertex Colors",
345 "Import vertex color attributes");
347 ot->srna, "import_attributes", true, "Vertex Attributes", "Import custom vertex attributes");
348
349 /* Only show `.ply` files by default. */
350 prop = RNA_def_string(ot->srna, "filter_glob", "*.ply", 0, "Extension Filter", "");
352}
353
354namespace blender::ed::io {
356{
357 auto fh = std::make_unique<blender::bke::FileHandlerType>();
358 STRNCPY(fh->idname, "IO_FH_ply");
359 STRNCPY(fh->import_operator, "WM_OT_ply_import");
360 STRNCPY(fh->export_operator, "WM_OT_ply_export");
361 STRNCPY(fh->label, "Stanford PLY");
362 STRNCPY(fh->file_extensions_str, ".ply");
363 fh->poll_drop = poll_file_object_drop;
364 bke::file_handler_add(std::move(fh));
365}
366} // namespace blender::ed::io
367
368#endif /* WITH_IO_PLY */
SpaceFile * CTX_wm_space_file(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
bool BKE_reports_contain(ReportList *reports, eReportType level)
Definition report.cc:342
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define FILE_MAX
bool BLI_path_extension_check(const char *path, const char *ext) ATTR_NONNULL(1
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define IFACE_(msgid)
#define MAX_IDPROP_NAME
Definition DNA_ID.h:185
@ FILE_SORT_DEFAULT
@ FILE_BLENDER
@ FILE_TYPE_FOLDER
@ FILE_DEFAULTDISPLAY
@ OPERATOR_RUNNING_MODAL
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension)
Definition filesel.cc:1466
void ED_outliner_select_sync_from_object_tag(bContext *C)
eIOAxis
@ IO_AXIS_Y
@ IO_AXIS_Z
void PLY_import(bContext *C, const PLYImportParams *import_params)
Definition IO_ply.cc:35
void PLY_export(bContext *C, const PLYExportParams *export_params)
Definition IO_ply.cc:28
ePLYVertexColorMode
Definition IO_ply.hh:21
@ PLY_VERTEX_COLOR_LINEAR
Definition IO_ply.hh:24
@ PLY_VERTEX_COLOR_NONE
Definition IO_ply.hh:22
@ PLY_VERTEX_COLOR_SRGB
Definition IO_ply.hh:23
@ PROP_HIDDEN
Definition RNA_types.hh:239
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
PanelLayout uiLayoutPanel(const bContext *C, uiLayout *layout, const char *idname, bool default_closed)
uiLayout * uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ WM_FILESEL_FILES
Definition WM_api.hh:937
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:934
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:939
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
@ FILE_SAVE
Definition WM_api.hh:946
@ OPTYPE_PRESET
Definition WM_types.hh:175
@ OPTYPE_UNDO
Definition WM_types.hh:162
#define ND_OB_ACTIVE
Definition WM_types.hh:407
#define ND_OB_SELECT
Definition WM_types.hh:409
#define NC_SCENE
Definition WM_types.hh:345
#define ND_LAYER_CONTENT
Definition WM_types.hh:420
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void WM_OT_ply_export(wmOperatorType *ot)
void WM_OT_ply_import(wmOperatorType *ot)
void file_handler_add(std::unique_ptr< FileHandlerType > file_handler)
bool poll_file_object_drop(const bContext *C, blender::bke::FileHandlerType *)
Definition io_utils.cc:57
Vector< std::string > paths_from_operator_properties(PointerRNA *ptr)
Definition io_utils.cc:74
void ply_file_handler_add()
int filesel_drop_import_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition io_utils.cc:25
const EnumPropertyItem io_transform_axis[]
void io_ui_forward_axis_update(Main *, Scene *, PointerRNA *ptr)
void io_ui_up_axis_update(Main *, Scene *, PointerRNA *ptr)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_update_runtime(PropertyRNA *prop, RNAPropertyUpdateFunc func)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
char filepath[1024]
Definition BKE_main.hh:136
char file_base_for_tests[FILE_MAX]
Definition IO_ply.hh:31
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
bool(* check)(bContext *C, wmOperator *op)
Definition WM_types.hh:1014
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
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)
bool WM_operator_winactive(bContext *C)