From d40d5e8d0f56cf5d2838b10007fb3e26b8cf72d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Wed, 23 Mar 2022 15:33:29 +0100 Subject: Cleanup: move Mesh Sequence Cache modifier to C++ This moves `MOD_meshsequencecache.c` to C++ and fixes compile warnings introduced from the change. This uses C++ style casts, as well as `nullptr` instead of `NULL`. This will allow to output `GeometrySets` from the modifier, which is C++. Differential Revision: https://developer.blender.org/D13662 --- source/blender/modifiers/CMakeLists.txt | 2 +- .../modifiers/intern/MOD_meshsequencecache.c | 445 -------------------- .../modifiers/intern/MOD_meshsequencecache.cc | 448 +++++++++++++++++++++ 3 files changed, 449 insertions(+), 446 deletions(-) delete mode 100644 source/blender/modifiers/intern/MOD_meshsequencecache.c create mode 100644 source/blender/modifiers/intern/MOD_meshsequencecache.cc diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 88984a652d7..a5e5bf36dcd 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -61,7 +61,7 @@ set(SRC intern/MOD_meshcache_pc2.c intern/MOD_meshcache_util.c intern/MOD_meshdeform.c - intern/MOD_meshsequencecache.c + intern/MOD_meshsequencecache.cc intern/MOD_mirror.c intern/MOD_multires.c intern/MOD_nodes.cc diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c deleted file mode 100644 index 14af22645e3..00000000000 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ /dev/null @@ -1,445 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup modifiers - */ - -#include - -#include "BLI_math_vector.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" - -#include "BLT_translation.h" - -#include "DNA_cachefile_types.h" -#include "DNA_defaults.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" - -#include "MEM_guardedalloc.h" - -#include "BKE_cachefile.h" -#include "BKE_context.h" -#include "BKE_lib_query.h" -#include "BKE_mesh.h" -#include "BKE_object.h" -#include "BKE_scene.h" -#include "BKE_screen.h" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "RNA_access.h" -#include "RNA_prototypes.h" - -#include "BLO_read_write.h" - -#include "DEG_depsgraph_build.h" -#include "DEG_depsgraph_query.h" - -#include "MOD_modifiertypes.h" -#include "MOD_ui_common.h" - -#if defined(WITH_USD) || defined(WITH_ALEMBIC) -# include "BKE_global.h" -# include "BKE_lib_id.h" -#endif - -#ifdef WITH_ALEMBIC -# include "ABC_alembic.h" -#endif - -#ifdef WITH_USD -# include "usd.h" -#endif - -static void initData(ModifierData *md) -{ - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier)); - - mcmd->cache_file = NULL; - mcmd->object_path[0] = '\0'; - mcmd->read_flag = MOD_MESHSEQ_READ_ALL; - - MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshSeqCacheModifierData), modifier); -} - -static void copyData(const ModifierData *md, ModifierData *target, const int flag) -{ -#if 0 - const MeshSeqCacheModifierData *mcmd = (const MeshSeqCacheModifierData *)md; -#endif - MeshSeqCacheModifierData *tmcmd = (MeshSeqCacheModifierData *)target; - - BKE_modifier_copydata_generic(md, target, flag); - - tmcmd->reader = NULL; - tmcmd->reader_object_path[0] = '\0'; -} - -static void freeData(ModifierData *md) -{ - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - if (mcmd->reader) { - mcmd->reader_object_path[0] = '\0'; - BKE_cachefile_reader_free(mcmd->cache_file, &mcmd->reader); - } -} - -static bool isDisabled(const struct Scene *UNUSED(scene), - ModifierData *md, - bool UNUSED(useRenderParams)) -{ - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - /* leave it up to the modifier to check the file is valid on calculation */ - return (mcmd->cache_file == NULL) || (mcmd->object_path[0] == '\0'); -} - -static Mesh *generate_bounding_box_mesh(Object *object, Mesh *org_mesh) -{ - BoundBox *bb = BKE_object_boundbox_get(object); - Mesh *result = BKE_mesh_new_nomain_from_template(org_mesh, 8, 0, 0, 24, 6); - - MVert *mvert = result->mvert; - for (int i = 0; i < 8; ++i) { - copy_v3_v3(mvert[i].co, bb->vec[i]); - } - - /* See DNA_object_types.h for the diagram showing the order of the vertices for a BoundBox. */ - static unsigned int loops_v[6][4] = { - {0, 4, 5, 1}, - {4, 7, 6, 5}, - {7, 3, 2, 6}, - {3, 0, 1, 2}, - {1, 5, 6, 2}, - {3, 7, 4, 0}, - }; - - MLoop *mloop = result->mloop; - for (int i = 0; i < 6; ++i) { - for (int j = 0; j < 4; ++j, ++mloop) { - mloop->v = loops_v[i][j]; - } - } - - MPoly *mpoly = result->mpoly; - for (int i = 0; i < 6; ++i) { - mpoly[i].loopstart = i * 4; - mpoly[i].totloop = 4; - } - - BKE_mesh_calc_edges(result, false, false); - - return result; -} - -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) -{ -#if defined(WITH_USD) || defined(WITH_ALEMBIC) - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - /* Only used to check whether we are operating on org data or not... */ - Mesh *me = (ctx->object->type == OB_MESH) ? ctx->object->data : NULL; - Mesh *org_mesh = mesh; - - Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); - CacheFile *cache_file = mcmd->cache_file; - const float frame = DEG_get_ctime(ctx->depsgraph); - const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); - const char *err_str = NULL; - - if (!mcmd->reader || !STREQ(mcmd->reader_object_path, mcmd->object_path)) { - STRNCPY(mcmd->reader_object_path, mcmd->object_path); - BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path); - if (!mcmd->reader) { - BKE_modifier_set_error( - ctx->object, md, "Could not create reader for file %s", cache_file->filepath); - return mesh; - } - } - - /* Do not process data if using a render procedural, return a box instead for displaying in the - * viewport. */ - if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(ctx->depsgraph))) { - return generate_bounding_box_mesh(ctx->object, org_mesh); - } - - /* If this invocation is for the ORCO mesh, and the mesh hasn't changed topology, we - * must return the mesh as-is instead of deforming it. */ - if (ctx->flag & MOD_APPLY_ORCO) { - switch (cache_file->type) { - case CACHEFILE_TYPE_ALEMBIC: -# ifdef WITH_ALEMBIC - if (!ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) { - return mesh; - } -# endif - break; - case CACHEFILE_TYPE_USD: -# ifdef WITH_USD - if (!USD_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) { - return mesh; - } -# endif - break; - case CACHE_FILE_TYPE_INVALID: - break; - } - } - - if (me != NULL) { - MVert *mvert = mesh->mvert; - MEdge *medge = mesh->medge; - MPoly *mpoly = mesh->mpoly; - - /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on - * flags) and duplicate those too. */ - if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) { - /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */ - mesh = (Mesh *)BKE_id_copy_ex(NULL, - &mesh->id, - NULL, - LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | - LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW); - } - } - - Mesh *result = NULL; - - switch (cache_file->type) { - case CACHEFILE_TYPE_ALEMBIC: { -# ifdef WITH_ALEMBIC - /* Time (in frames or seconds) between two velocity samples. Automatically computed to - * scale the velocity vectors at render time for generating proper motion blur data. */ - float velocity_scale = mcmd->velocity_scale; - if (mcmd->cache_file->velocity_unit == CACHEFILE_VELOCITY_UNIT_FRAME) { - velocity_scale *= FPS; - } - - result = ABC_read_mesh(mcmd->reader, - ctx->object, - mesh, - time, - &err_str, - mcmd->read_flag, - mcmd->cache_file->velocity_name, - velocity_scale); -# endif - break; - } - case CACHEFILE_TYPE_USD: -# ifdef WITH_USD - result = USD_read_mesh( - mcmd->reader, ctx->object, mesh, time * FPS, &err_str, mcmd->read_flag); -# endif - break; - case CACHE_FILE_TYPE_INVALID: - break; - } - - if (err_str) { - BKE_modifier_set_error(ctx->object, md, "%s", err_str); - } - - if (!ELEM(result, NULL, mesh) && (mesh != org_mesh)) { - BKE_id_free(NULL, mesh); - mesh = org_mesh; - } - - return result ? result : mesh; -#else - UNUSED_VARS(ctx, md, generate_bounding_box_mesh); - return mesh; -#endif -} - -static bool dependsOnTime(Scene *scene, ModifierData *md, const int dag_eval_mode) -{ -#if defined(WITH_USD) || defined(WITH_ALEMBIC) - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - /* Do not evaluate animations if using the render engine procedural. */ - return (mcmd->cache_file != NULL) && - !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene, dag_eval_mode); -#else - UNUSED_VARS(scene, md, dag_eval_mode); - return false; -#endif -} - -static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) -{ - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_CB_USER); -} - -static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) -{ - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - if (mcmd->cache_file != NULL) { - DEG_add_object_cache_relation( - ctx->node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File"); - } -} - -static void panel_draw(const bContext *C, Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA ob_ptr; - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - - PointerRNA cache_file_ptr = RNA_pointer_get(ptr, "cache_file"); - bool has_cache_file = !RNA_pointer_is_null(&cache_file_ptr); - - uiLayoutSetPropSep(layout, true); - - uiTemplateCacheFile(layout, C, ptr, "cache_file"); - - if (has_cache_file) { - uiItemPointerR(layout, ptr, "object_path", &cache_file_ptr, "object_paths", NULL, ICON_NONE); - } - - if (RNA_enum_get(&ob_ptr, "type") == OB_MESH) { - uiItemR(layout, ptr, "read_data", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_vertex_interpolation", 0, NULL, ICON_NONE); - } - - modifier_panel_end(layout, ptr); -} - -static void velocity_panel_draw(const bContext *UNUSED(C), Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA ob_ptr; - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - - PointerRNA fileptr; - if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { - return; - } - - uiLayoutSetPropSep(layout, true); - uiTemplateCacheFileVelocity(layout, &fileptr); - uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE); -} - -static void time_panel_draw(const bContext *UNUSED(C), Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA ob_ptr; - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - - PointerRNA fileptr; - if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { - return; - } - - uiLayoutSetPropSep(layout, true); - uiTemplateCacheFileTimeSettings(layout, &fileptr); -} - -static void render_procedural_panel_draw(const bContext *C, Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA ob_ptr; - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - - PointerRNA fileptr; - if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { - return; - } - - uiLayoutSetPropSep(layout, true); - uiTemplateCacheFileProcedural(layout, C, &fileptr); -} - -static void override_layers_panel_draw(const bContext *C, Panel *panel) -{ - uiLayout *layout = panel->layout; - - PointerRNA ob_ptr; - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - - PointerRNA fileptr; - if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { - return; - } - - uiLayoutSetPropSep(layout, true); - uiTemplateCacheFileLayers(layout, C, &fileptr); -} - -static void panelRegister(ARegionType *region_type) -{ - PanelType *panel_type = modifier_panel_register( - region_type, eModifierType_MeshSequenceCache, panel_draw); - modifier_subpanel_register(region_type, "time", "Time", NULL, time_panel_draw, panel_type); - modifier_subpanel_register(region_type, - "render_procedural", - "Render Procedural", - NULL, - render_procedural_panel_draw, - panel_type); - modifier_subpanel_register( - region_type, "velocity", "Velocity", NULL, velocity_panel_draw, panel_type); - modifier_subpanel_register(region_type, - "override_layers", - "Override Layers", - NULL, - override_layers_panel_draw, - panel_type); -} - -static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md) -{ - MeshSeqCacheModifierData *msmcd = (MeshSeqCacheModifierData *)md; - msmcd->reader = NULL; - msmcd->reader_object_path[0] = '\0'; -} - -ModifierTypeInfo modifierType_MeshSequenceCache = { - /* name */ "MeshSequenceCache", - /* structName */ "MeshSeqCacheModifierData", - /* structSize */ sizeof(MeshSeqCacheModifierData), - /* srna */ &RNA_MeshSequenceCacheModifier, - /* type */ eModifierTypeType_Constructive, - /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, - /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */ - - /* copyData */ copyData, - - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* modifyMesh */ modifyMesh, - /* modifyGeometrySet */ NULL, - - /* initData */ initData, - /* requiredDataMask */ NULL, - /* freeData */ freeData, - /* isDisabled */ isDisabled, - /* updateDepsgraph */ updateDepsgraph, - /* dependsOnTime */ dependsOnTime, - /* dependsOnNormals */ NULL, - /* foreachIDLink */ foreachIDLink, - /* foreachTexLink */ NULL, - /* freeRuntimeData */ NULL, - /* panelRegister */ panelRegister, - /* blendWrite */ NULL, - /* blendRead */ blendRead, -}; diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc new file mode 100644 index 00000000000..5c895824a01 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc @@ -0,0 +1,448 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup modifiers + */ + +#include + +#include "BLI_math_vector.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "DNA_cachefile_types.h" +#include "DNA_defaults.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_cachefile.h" +#include "BKE_context.h" +#include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_scene.h" +#include "BKE_screen.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "RNA_access.h" +#include "RNA_prototypes.h" + +#include "BLO_read_write.h" + +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +#include "MOD_modifiertypes.h" +#include "MOD_ui_common.h" + +#if defined(WITH_USD) || defined(WITH_ALEMBIC) +# include "BKE_global.h" +# include "BKE_lib_id.h" +#endif + +#ifdef WITH_ALEMBIC +# include "ABC_alembic.h" +#endif + +#ifdef WITH_USD +# include "usd.h" +#endif + +static void initData(ModifierData *md) +{ + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier)); + + mcmd->cache_file = nullptr; + mcmd->object_path[0] = '\0'; + mcmd->read_flag = MOD_MESHSEQ_READ_ALL; + + MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshSeqCacheModifierData), modifier); +} + +static void copyData(const ModifierData *md, ModifierData *target, const int flag) +{ +#if 0 + const MeshSeqCacheModifierData *mcmd = (const MeshSeqCacheModifierData *)md; +#endif + MeshSeqCacheModifierData *tmcmd = (MeshSeqCacheModifierData *)target; + + BKE_modifier_copydata_generic(md, target, flag); + + tmcmd->reader = nullptr; + tmcmd->reader_object_path[0] = '\0'; +} + +static void freeData(ModifierData *md) +{ + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + + if (mcmd->reader) { + mcmd->reader_object_path[0] = '\0'; + BKE_cachefile_reader_free(mcmd->cache_file, &mcmd->reader); + } +} + +static bool isDisabled(const struct Scene *UNUSED(scene), + ModifierData *md, + bool UNUSED(useRenderParams)) +{ + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + + /* leave it up to the modifier to check the file is valid on calculation */ + return (mcmd->cache_file == nullptr) || (mcmd->object_path[0] == '\0'); +} + +static Mesh *generate_bounding_box_mesh(Object *object, Mesh *org_mesh) +{ + BoundBox *bb = BKE_object_boundbox_get(object); + Mesh *result = BKE_mesh_new_nomain_from_template(org_mesh, 8, 0, 0, 24, 6); + + MVert *mvert = result->mvert; + for (int i = 0; i < 8; ++i) { + copy_v3_v3(mvert[i].co, bb->vec[i]); + } + + /* See DNA_object_types.h for the diagram showing the order of the vertices for a BoundBox. */ + static unsigned int loops_v[6][4] = { + {0, 4, 5, 1}, + {4, 7, 6, 5}, + {7, 3, 2, 6}, + {3, 0, 1, 2}, + {1, 5, 6, 2}, + {3, 7, 4, 0}, + }; + + MLoop *mloop = result->mloop; + for (int i = 0; i < 6; ++i) { + for (int j = 0; j < 4; ++j, ++mloop) { + mloop->v = loops_v[i][j]; + } + } + + MPoly *mpoly = result->mpoly; + for (int i = 0; i < 6; ++i) { + mpoly[i].loopstart = i * 4; + mpoly[i].totloop = 4; + } + + BKE_mesh_calc_edges(result, false, false); + + return result; +} + +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +{ +#if defined(WITH_USD) || defined(WITH_ALEMBIC) + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + + /* Only used to check whether we are operating on org data or not... */ + Mesh *me = (ctx->object->type == OB_MESH) ? static_cast(ctx->object->data) : nullptr; + Mesh *org_mesh = mesh; + + Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); + CacheFile *cache_file = mcmd->cache_file; + const float frame = DEG_get_ctime(ctx->depsgraph); + const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); + const char *err_str = nullptr; + + if (!mcmd->reader || !STREQ(mcmd->reader_object_path, mcmd->object_path)) { + STRNCPY(mcmd->reader_object_path, mcmd->object_path); + BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path); + if (!mcmd->reader) { + BKE_modifier_set_error( + ctx->object, md, "Could not create reader for file %s", cache_file->filepath); + return mesh; + } + } + + /* Do not process data if using a render procedural, return a box instead for displaying in the + * viewport. */ + if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(ctx->depsgraph))) { + return generate_bounding_box_mesh(ctx->object, org_mesh); + } + + /* If this invocation is for the ORCO mesh, and the mesh hasn't changed topology, we + * must return the mesh as-is instead of deforming it. */ + if (ctx->flag & MOD_APPLY_ORCO) { + switch (cache_file->type) { + case CACHEFILE_TYPE_ALEMBIC: +# ifdef WITH_ALEMBIC + if (!ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) { + return mesh; + } +# endif + break; + case CACHEFILE_TYPE_USD: +# ifdef WITH_USD + if (!USD_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) { + return mesh; + } +# endif + break; + case CACHE_FILE_TYPE_INVALID: + break; + } + } + + if (me != nullptr) { + MVert *mvert = mesh->mvert; + MEdge *medge = mesh->medge; + MPoly *mpoly = mesh->mpoly; + + /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on + * flags) and duplicate those too. */ + if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) { + /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */ + mesh = reinterpret_cast( + BKE_id_copy_ex(nullptr, + &mesh->id, + nullptr, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW)); + } + } + + Mesh *result = nullptr; + + switch (cache_file->type) { + case CACHEFILE_TYPE_ALEMBIC: { +# ifdef WITH_ALEMBIC + /* Time (in frames or seconds) between two velocity samples. Automatically computed to + * scale the velocity vectors at render time for generating proper motion blur data. */ + float velocity_scale = mcmd->velocity_scale; + if (mcmd->cache_file->velocity_unit == CACHEFILE_VELOCITY_UNIT_FRAME) { + velocity_scale *= FPS; + } + + result = ABC_read_mesh(mcmd->reader, + ctx->object, + mesh, + time, + &err_str, + mcmd->read_flag, + mcmd->cache_file->velocity_name, + velocity_scale); +# endif + break; + } + case CACHEFILE_TYPE_USD: +# ifdef WITH_USD + result = USD_read_mesh( + mcmd->reader, ctx->object, mesh, time * FPS, &err_str, mcmd->read_flag); +# endif + break; + case CACHE_FILE_TYPE_INVALID: + break; + } + + if (err_str) { + BKE_modifier_set_error(ctx->object, md, "%s", err_str); + } + + if (!ELEM(result, nullptr, mesh) && (mesh != org_mesh)) { + BKE_id_free(nullptr, mesh); + mesh = org_mesh; + } + + return result ? result : mesh; +#else + UNUSED_VARS(ctx, md, generate_bounding_box_mesh); + return mesh; +#endif +} + +static bool dependsOnTime(Scene *scene, ModifierData *md, const int dag_eval_mode) +{ +#if defined(WITH_USD) || defined(WITH_ALEMBIC) + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + /* Do not evaluate animations if using the render engine procedural. */ + return (mcmd->cache_file != nullptr) && + !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene, dag_eval_mode); +#else + UNUSED_VARS(scene, md, dag_eval_mode); + return false; +#endif +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + + walk(userData, ob, reinterpret_cast(&mcmd->cache_file), IDWALK_CB_USER); +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + MeshSeqCacheModifierData *mcmd = reinterpret_cast(md); + + if (mcmd->cache_file != nullptr) { + DEG_add_object_cache_relation( + ctx->node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File"); + } +} + +static void panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + PointerRNA cache_file_ptr = RNA_pointer_get(ptr, "cache_file"); + bool has_cache_file = !RNA_pointer_is_null(&cache_file_ptr); + + uiLayoutSetPropSep(layout, true); + + uiTemplateCacheFile(layout, C, ptr, "cache_file"); + + if (has_cache_file) { + uiItemPointerR( + layout, ptr, "object_path", &cache_file_ptr, "object_paths", nullptr, ICON_NONE); + } + + if (RNA_enum_get(&ob_ptr, "type") == OB_MESH) { + uiItemR(layout, ptr, "read_data", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(layout, ptr, "use_vertex_interpolation", 0, nullptr, ICON_NONE); + } + + modifier_panel_end(layout, ptr); +} + +static void velocity_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + PointerRNA fileptr; + if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { + return; + } + + uiLayoutSetPropSep(layout, true); + uiTemplateCacheFileVelocity(layout, &fileptr); + uiItemR(layout, ptr, "velocity_scale", 0, nullptr, ICON_NONE); +} + +static void time_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + PointerRNA fileptr; + if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { + return; + } + + uiLayoutSetPropSep(layout, true); + uiTemplateCacheFileTimeSettings(layout, &fileptr); +} + +static void render_procedural_panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + PointerRNA fileptr; + if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { + return; + } + + uiLayoutSetPropSep(layout, true); + uiTemplateCacheFileProcedural(layout, C, &fileptr); +} + +static void override_layers_panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + PointerRNA fileptr; + if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) { + return; + } + + uiLayoutSetPropSep(layout, true); + uiTemplateCacheFileLayers(layout, C, &fileptr); +} + +static void panelRegister(ARegionType *region_type) +{ + PanelType *panel_type = modifier_panel_register( + region_type, eModifierType_MeshSequenceCache, panel_draw); + modifier_subpanel_register(region_type, "time", "Time", nullptr, time_panel_draw, panel_type); + modifier_subpanel_register(region_type, + "render_procedural", + "Render Procedural", + nullptr, + render_procedural_panel_draw, + panel_type); + modifier_subpanel_register( + region_type, "velocity", "Velocity", nullptr, velocity_panel_draw, panel_type); + modifier_subpanel_register(region_type, + "override_layers", + "Override Layers", + NULL, + override_layers_panel_draw, + panel_type); +} + +static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md) +{ + MeshSeqCacheModifierData *msmcd = reinterpret_cast(md); + msmcd->reader = nullptr; + msmcd->reader_object_path[0] = '\0'; +} + +ModifierTypeInfo modifierType_MeshSequenceCache = { + /* name */ "MeshSequenceCache", + /* structName */ "MeshSeqCacheModifierData", + /* structSize */ sizeof(MeshSeqCacheModifierData), + /* srna */ &RNA_MeshSequenceCacheModifier, + /* type */ eModifierTypeType_Constructive, + /* flags */ + static_cast(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs), + /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */ + + /* copyData */ copyData, + + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ modifyMesh, + /* modifyGeometrySet */ nullptr, + + /* initData */ initData, + /* requiredDataMask */ nullptr, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, + /* panelRegister */ panelRegister, + /* blendWrite */ nullptr, + /* blendRead */ blendRead, +}; -- cgit v1.2.3