Blender V4.5
MOD_meshsequencecache.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
8
9#include <cstring>
10
11#include "BLI_math_vector.hh"
12#include "BLI_string.h"
13#include "BLI_utildefines.h"
14
15#include "BLT_translation.hh"
16
17#include "DNA_cachefile_types.h"
18#include "DNA_defaults.h"
19#include "DNA_mesh_types.h"
20#include "DNA_modifier_types.h"
21#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24#include "DNA_screen_types.h"
25
26#include "MEM_guardedalloc.h"
27
28#include "BKE_cachefile.hh"
29#include "BKE_geometry_set.hh"
30#include "BKE_lib_query.hh"
31#include "BKE_mesh.hh"
32
33#include "UI_interface.hh"
34#include "UI_resources.hh"
35
36#include "RNA_access.hh"
37#include "RNA_prototypes.hh"
38
41
43
44#include "MOD_modifiertypes.hh"
45#include "MOD_ui_common.hh"
46
47#if defined(WITH_USD) || defined(WITH_ALEMBIC)
48# include "BKE_lib_id.hh"
49#endif
50
51#ifdef WITH_ALEMBIC
52# include "ABC_alembic.h"
53#endif
54
55#ifdef WITH_USD
56# include "usd.hh"
57#endif
58
59using namespace blender;
60
61static void init_data(ModifierData *md)
62{
63 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
64
66
67 mcmd->cache_file = nullptr;
68 mcmd->object_path[0] = '\0';
70
72}
73
74static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
75{
76#if 0
77 const MeshSeqCacheModifierData *mcmd = (const MeshSeqCacheModifierData *)md;
78#endif
80
82
83 tmcmd->reader = nullptr;
84 tmcmd->reader_object_path[0] = '\0';
85}
86
87static void free_data(ModifierData *md)
88{
89 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
90
91 if (mcmd->reader) {
92 mcmd->reader_object_path[0] = '\0';
94 }
95}
96
97static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
98{
99 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
100
101 /* leave it up to the modifier to check the file is valid on calculation */
102 return (mcmd->cache_file == nullptr) || (mcmd->object_path[0] == '\0');
103}
104
105#if defined(WITH_USD) || defined(WITH_ALEMBIC)
106
107/* Return true if the modifier evaluation is for the ORCO mesh and the mesh hasn't changed
108 * topology.
109 */
110static bool can_use_mesh_for_orco_evaluation(MeshSeqCacheModifierData *mcmd,
111 const ModifierEvalContext *ctx,
112 const Mesh *mesh,
113 const double frame_offset,
114 const double time_offset,
115 const char **r_err_str)
116{
117 if ((ctx->flag & MOD_APPLY_ORCO) == 0) {
118 return false;
119 }
120
121 CacheFile *cache_file = mcmd->cache_file;
122
123 switch (cache_file->type) {
125# ifdef WITH_ALEMBIC
126 if (!ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time_offset, r_err_str)) {
127 return true;
128 }
129# endif
130 break;
132# ifdef WITH_USD
134 mcmd->reader, ctx->object, mesh, frame_offset, r_err_str))
135 {
136 return true;
137 }
138# endif
139 break;
141 break;
142 }
143
144 return false;
145}
146
147static Mesh *generate_bounding_box_mesh(const std::optional<Bounds<float3>> &bounds,
148 Material **mat,
149 short totcol)
150{
151 if (!bounds) {
152 return nullptr;
153 }
154
155 Mesh *result = geometry::create_cuboid_mesh(bounds->max - bounds->min, 2, 2, 2);
156 if (mat) {
157 result->mat = static_cast<Material **>(MEM_dupallocN(mat));
158 result->totcol = totcol;
159 }
160
162
163 return result;
164}
165
166#endif
167
169 const ModifierEvalContext *ctx,
170 bke::GeometrySet *geometry_set)
171{
172#if defined(WITH_USD) || defined(WITH_ALEMBIC)
173 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
174
176 CacheFile *cache_file = mcmd->cache_file;
177 const double frame = double(DEG_get_ctime(ctx->depsgraph));
178 const double frame_offset = BKE_cachefile_frame_offset(cache_file, frame);
179 const double time_offset = BKE_cachefile_time_offset(cache_file, frame, FPS);
180 const char *err_str = nullptr;
181
182 if (!mcmd->reader || !STREQ(mcmd->reader_object_path, mcmd->object_path)) {
184 BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path);
185 if (!mcmd->reader) {
187 ctx->object, md, "Could not create cache reader for file %s", cache_file->filepath);
188 return;
189 }
190 }
191
192 if (geometry_set->has_mesh()) {
193 const Mesh *mesh = geometry_set->get_mesh();
194 if (can_use_mesh_for_orco_evaluation(mcmd, ctx, mesh, frame_offset, time_offset, &err_str)) {
195 return;
196 }
197 }
198
199 /* Do not process data if using a render procedural, return a box instead for displaying in the
200 * viewport. */
201 if (BKE_cache_file_uses_render_procedural(cache_file, scene)) {
202 Mesh *bbox = nullptr;
203 if (geometry_set->has_mesh()) {
204 const Mesh *mesh = geometry_set->get_mesh();
205 bbox = generate_bounding_box_mesh(mesh->bounds_min_max(), mesh->mat, mesh->totcol);
206 }
207 else if (geometry_set->has_pointcloud()) {
208 const PointCloud *pointcloud = geometry_set->get_pointcloud();
209 bbox = generate_bounding_box_mesh(
210 pointcloud->bounds_min_max(), pointcloud->mat, pointcloud->totcol);
211 }
212
213 *geometry_set = bke::GeometrySet::from_mesh(bbox);
214 return;
215 }
216
217 /* Time (in frames or seconds) between two velocity samples. Automatically computed to
218 * scale the velocity vectors at render time for generating proper motion blur data. */
219# ifdef WITH_ALEMBIC
220 float velocity_scale = mcmd->velocity_scale;
222 velocity_scale *= FPS;
223 }
224# endif
225
226 switch (cache_file->type) {
228# ifdef WITH_ALEMBIC
230 params.time = time_offset;
231 params.read_flags = mcmd->read_flag;
232 params.velocity_name = mcmd->cache_file->velocity_name;
233 params.velocity_scale = velocity_scale;
234 ABC_read_geometry(mcmd->reader, ctx->object, *geometry_set, &params, &err_str);
235# endif
236 break;
237 }
238 case CACHEFILE_TYPE_USD: {
239# ifdef WITH_USD
241 frame_offset, mcmd->read_flag);
243 mcmd->reader, ctx->object, *geometry_set, params, &err_str);
244# endif
245 break;
246 }
248 break;
249 }
250
251 if (err_str) {
252 BKE_modifier_set_error(ctx->object, md, "%s", err_str);
253 }
254
255#else
256 UNUSED_VARS(ctx, md, geometry_set);
257 return;
258#endif
259}
260
261static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
262{
263#if defined(WITH_USD) || defined(WITH_ALEMBIC)
264 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
265
266 /* Only used to check whether we are operating on org data or not... */
267 Mesh *object_mesh = (ctx->object->type == OB_MESH) ? static_cast<Mesh *>(ctx->object->data) :
268 nullptr;
269 Mesh *org_mesh = mesh;
270
272 CacheFile *cache_file = mcmd->cache_file;
273 const double frame = double(DEG_get_ctime(ctx->depsgraph));
274 const double frame_offset = BKE_cachefile_frame_offset(cache_file, frame);
275 const double time_offset = BKE_cachefile_time_offset(cache_file, frame, FPS);
276 const char *err_str = nullptr;
277
278 if (!mcmd->reader || !STREQ(mcmd->reader_object_path, mcmd->object_path)) {
280 BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path);
281 if (!mcmd->reader) {
283 ctx->object, md, "Could not create reader for file %s", cache_file->filepath);
284 return mesh;
285 }
286 }
287
288 /* Do not process data if using a render procedural, return a box instead for displaying in the
289 * viewport. */
290 if (BKE_cache_file_uses_render_procedural(cache_file, scene)) {
291 return generate_bounding_box_mesh(org_mesh->bounds_min_max(), org_mesh->mat, org_mesh->totcol);
292 }
293
294 /* If this invocation is for the ORCO mesh, and the mesh hasn't changed topology, we
295 * must return the mesh as-is instead of deforming it. */
296 if (can_use_mesh_for_orco_evaluation(mcmd, ctx, mesh, frame_offset, time_offset, &err_str)) {
297 return mesh;
298 }
299
300 if (object_mesh != nullptr) {
301 const Span<float3> mesh_positions = mesh->vert_positions();
302 const Span<blender::int2> mesh_edges = mesh->edges();
303 const blender::OffsetIndices mesh_faces = mesh->faces();
304 const Span<float3> me_positions = object_mesh->vert_positions();
305 const Span<blender::int2> me_edges = object_mesh->edges();
306 const blender::OffsetIndices me_faces = object_mesh->faces();
307
308 /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on
309 * flags) and duplicate those too.
310 * XXX(Hans): This probably isn't true anymore with various copy-on-eval improvements, etc. */
311 if ((me_positions.data() == mesh_positions.data()) || (me_edges.data() == mesh_edges.data()) ||
312 (me_faces.data() == mesh_faces.data()))
313 {
314 /* We need to duplicate data here, otherwise we'll modify org mesh, see #51701. */
315 mesh = reinterpret_cast<Mesh *>(
316 BKE_id_copy_ex(nullptr,
317 &mesh->id,
318 nullptr,
321 }
322 }
323
326 modify_geometry_set(md, ctx, &geometry_set);
327 Mesh *result = geometry_set.get_component_for_write<bke::MeshComponent>().release();
328
329 if (!ELEM(result, nullptr, mesh) && (mesh != org_mesh)) {
330 BKE_id_free(nullptr, mesh);
331 mesh = org_mesh;
332 }
333
334 return result ? result : mesh;
335#else
336 UNUSED_VARS(ctx, md);
337 return mesh;
338#endif
339}
340
341static bool depends_on_time(Scene *scene, ModifierData *md)
342{
343#if defined(WITH_USD) || defined(WITH_ALEMBIC)
344 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
345 /* Do not evaluate animations if using the render engine procedural. */
346 return (mcmd->cache_file != nullptr) &&
348#else
349 UNUSED_VARS(scene, md);
350 return false;
351#endif
352}
353
354static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
355{
356 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
357
358 walk(user_data, ob, reinterpret_cast<ID **>(&mcmd->cache_file), IDWALK_CB_USER);
359}
360
362{
363 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
364
365 if (mcmd->cache_file != nullptr) {
367 ctx->node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File");
368 }
369}
370
371static void panel_draw(const bContext *C, Panel *panel)
372{
373 uiLayout *layout = panel->layout;
374
375 PointerRNA ob_ptr;
377
378 PointerRNA cache_file_ptr = RNA_pointer_get(ptr, "cache_file");
379 bool has_cache_file = !RNA_pointer_is_null(&cache_file_ptr);
380
381 uiLayoutSetPropSep(layout, true);
382
383 uiTemplateCacheFile(layout, C, ptr, "cache_file");
384
385 if (has_cache_file) {
387 layout, ptr, "object_path", &cache_file_ptr, "object_paths", std::nullopt, ICON_NONE);
388 }
389
390 if (RNA_enum_get(&ob_ptr, "type") == OB_MESH) {
391 layout->prop(ptr, "read_data", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
392 layout->prop(ptr, "use_vertex_interpolation", UI_ITEM_NONE, std::nullopt, ICON_NONE);
393 }
394 else if (RNA_enum_get(&ob_ptr, "type") == OB_CURVES) {
395 layout->prop(ptr, "use_vertex_interpolation", UI_ITEM_NONE, std::nullopt, ICON_NONE);
396 }
397
399}
400
401static void velocity_panel_draw(const bContext * /*C*/, Panel *panel)
402{
403 uiLayout *layout = panel->layout;
404
405 PointerRNA ob_ptr;
407
408 PointerRNA fileptr;
409 if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
410 return;
411 }
412
413 uiLayoutSetPropSep(layout, true);
414 uiTemplateCacheFileVelocity(layout, &fileptr);
415 layout->prop(ptr, "velocity_scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
416}
417
418static void time_panel_draw(const bContext * /*C*/, Panel *panel)
419{
420 uiLayout *layout = panel->layout;
421
422 PointerRNA ob_ptr;
424
425 PointerRNA fileptr;
426 if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
427 return;
428 }
429
430 uiLayoutSetPropSep(layout, true);
431 uiTemplateCacheFileTimeSettings(layout, &fileptr);
432}
433
434static void render_procedural_panel_draw(const bContext *C, Panel *panel)
435{
436 uiLayout *layout = panel->layout;
437
438 PointerRNA ob_ptr;
440
441 PointerRNA fileptr;
442 if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
443 return;
444 }
445
446 uiLayoutSetPropSep(layout, true);
447 uiTemplateCacheFileProcedural(layout, C, &fileptr);
448}
449
450static void override_layers_panel_draw(const bContext *C, Panel *panel)
451{
452 uiLayout *layout = panel->layout;
453
454 PointerRNA ob_ptr;
456
457 PointerRNA fileptr;
458 if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
459 return;
460 }
461
462 uiLayoutSetPropSep(layout, true);
463 uiTemplateCacheFileLayers(layout, C, &fileptr);
464}
465
466static void panel_register(ARegionType *region_type)
467{
470 modifier_subpanel_register(region_type, "time", "Time", nullptr, time_panel_draw, panel_type);
471 modifier_subpanel_register(region_type,
472 "render_procedural",
473 "Render Procedural",
474 nullptr,
476 panel_type);
478 region_type, "velocity", "Velocity", nullptr, velocity_panel_draw, panel_type);
479 modifier_subpanel_register(region_type,
480 "override_layers",
481 "Override Layers",
482 nullptr,
484 panel_type);
485}
486
487static void blend_read(BlendDataReader * /*reader*/, ModifierData *md)
488{
489 MeshSeqCacheModifierData *msmcd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
490 msmcd->reader = nullptr;
491 msmcd->reader_object_path[0] = '\0';
492}
493
495 /*idname*/ "MeshSequenceCache",
496 /*name*/ N_("MeshSequenceCache"),
497 /*struct_name*/ "MeshSeqCacheModifierData",
498 /*struct_size*/ sizeof(MeshSeqCacheModifierData),
499 /*srna*/ &RNA_MeshSequenceCacheModifier,
501 /*flags*/
503 /*icon*/ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */
504
505 /*copy_data*/ copy_data,
506
507 /*deform_verts*/ nullptr,
508 /*deform_matrices*/ nullptr,
509 /*deform_verts_EM*/ nullptr,
510 /*deform_matrices_EM*/ nullptr,
511 /*modify_mesh*/ modify_mesh,
512 /*modify_geometry_set*/ modify_geometry_set,
513
514 /*init_data*/ init_data,
515 /*required_data_mask*/ nullptr,
516 /*free_data*/ free_data,
517 /*is_disabled*/ is_disabled,
518 /*update_depsgraph*/ update_depsgraph,
519 /*depends_on_time*/ depends_on_time,
520 /*depends_on_normals*/ nullptr,
521 /*foreach_ID_link*/ foreach_ID_link,
522 /*foreach_tex_link*/ nullptr,
523 /*free_runtime_data*/ nullptr,
524 /*panel_register*/ panel_register,
525 /*blend_write*/ nullptr,
526 /*blend_read*/ blend_read,
527 /*foreach_cache*/ nullptr,
528};
bool ABC_mesh_topology_changed(struct CacheReader *reader, struct Object *ob, const struct Mesh *existing_mesh, double time, const char **r_err_str)
bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, Scene *scene)
Definition cachefile.cc:415
void BKE_cachefile_reader_free(CacheFile *cache_file, CacheReader **reader)
Definition cachefile.cc:207
double BKE_cachefile_time_offset(const CacheFile *cache_file, double time, double fps)
Definition cachefile.cc:401
double BKE_cachefile_frame_offset(const CacheFile *cache_file, double time)
Definition cachefile.cc:408
void BKE_cachefile_reader_open(CacheFile *cache_file, CacheReader **reader, Object *object, const char *object_path)
Definition cachefile.cc:157
void BKE_id_free(Main *bmain, void *idv)
@ LIB_ID_COPY_NO_PREVIEW
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_CREATE_NO_DEG_TAG
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
@ IDWALK_CB_USER
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_AcceptsMesh
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
@ MOD_APPLY_ORCO
#define BLI_assert(a)
Definition BLI_assert.h:46
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define UNUSED_VARS(...)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
void DEG_add_object_cache_relation(DepsNodeHandle *handle, CacheFile *cache_file, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_CACHE
float DEG_get_ctime(const Depsgraph *graph)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ CACHEFILE_VELOCITY_UNIT_FRAME
@ CACHE_FILE_TYPE_INVALID
@ CACHEFILE_TYPE_ALEMBIC
@ CACHEFILE_TYPE_USD
#define DNA_struct_default_get(struct_name)
@ eModifierType_MeshSequenceCache
#define MOD_MESHSEQ_READ_ALL
Object is a sort of wrapper for general info.
@ OB_MESH
@ OB_CURVES
#define FPS
static bool is_disabled
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void blend_read(BlendDataReader *, ModifierData *md)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:271
static bool depends_on_time(Scene *, ModifierData *)
Definition MOD_build.cc:47
ModifierTypeInfo modifierType_MeshSequenceCache
static void override_layers_panel_draw(const bContext *C, Panel *panel)
static void velocity_panel_draw(const bContext *, Panel *panel)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void time_panel_draw(const bContext *, Panel *panel)
static void render_procedural_panel_draw(const bContext *C, Panel *panel)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
#define C
Definition RandGen.cpp:29
void uiTemplateCacheFileProcedural(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
void uiTemplateCacheFileLayers(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
bool uiTemplateCacheFilePointer(PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *r_file_ptr)
void uiTemplateCacheFileVelocity(uiLayout *layout, PointerRNA *fileptr)
void uiTemplateCacheFileTimeSettings(uiLayout *layout, PointerRNA *fileptr)
void uiTemplateCacheFile(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname)
@ UI_ITEM_R_EXPAND
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *searchptr, blender::StringRefNull searchpropname, std::optional< blender::StringRefNull > name, int icon)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void ABC_read_geometry(CacheReader *reader, Object *ob, blender::bke::GeometrySet &geometry_set, const ABCReadParams *params, const char **r_err_str)
constexpr const T * data() const
Definition BLI_span.hh:215
static void update_depsgraph(tGraphSliderOp *gso)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void mesh_translate(Mesh &mesh, const float3 &translation, bool do_shape_keys)
Mesh * create_cuboid_mesh(const float3 &size, int verts_x, int verts_y, int verts_z, const std::optional< StringRef > &uv_id)
bool USD_mesh_topology_changed(CacheReader *reader, const Object *ob, const Mesh *existing_mesh, const double time, const char **r_err_str)
USDMeshReadParams create_mesh_read_params(const double motion_sample_time, const int read_flags)
void USD_read_geometry(CacheReader *reader, const Object *ob, blender::bke::GeometrySet &geometry_set, const USDMeshReadParams params, const char **r_err_str)
T midpoint(const T &a, const T &b)
static bool depends_on_time(Scene *, ModifierData *md)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void init_data(ModifierData *md)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void panel_draw(const bContext *C, Panel *panel)
static void modify_geometry_set(ModifierData *md, const ModifierEvalContext *ctx, bke::GeometrySet *geometry_set)
static void free_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void blend_read(BlendDataReader *reader, ModifierData *md)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
bool RNA_pointer_is_null(const PointerRNA *ptr)
int RNA_enum_get(PointerRNA *ptr, const char *name)
char filepath[1024]
char velocity_name[64]
Definition DNA_ID.h:404
struct CacheReader * reader
struct Material ** mat
short totcol
ModifierApplyFlag flag
struct uiLayout * layout
struct Material ** mat
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const PointCloud * get_pointcloud() const
const Mesh * get_mesh() const
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4226
uint8_t flag
Definition wm_window.cc:139