diff options
18 files changed, 229 insertions, 252 deletions
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index 36daa50e095..e437273c1be 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -364,9 +364,6 @@ void AbcObjectReader::addCacheModifier() id_us_plus(&mcmd->cache_file->id); BLI_strncpy(mcmd->object_path, m_iobject.getFullName().c_str(), FILE_MAX); - - mcmd->reader = reinterpret_cast<CacheReader *>(this); - this->incref(); } chrono_t AbcObjectReader::minTime() const diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 3ff3fbe2001..b502692d0e5 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -627,6 +627,7 @@ struct ImportJobData { char filename[1024]; ImportSettings settings; + ArchiveReader *archive; std::vector<AbcObjectReader *> readers; short *stop; @@ -672,9 +673,9 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa cache_file->is_sequence = data->settings.is_sequence; cache_file->scale = data->settings.scale; - cache_file->handle = handle_from_archive(archive); - BLI_strncpy(cache_file->filepath, data->filename, 1024); + STRNCPY(cache_file->filepath, data->filename); + data->archive = archive; data->settings.cache_file = cache_file; *data->do_update = true; @@ -855,6 +856,7 @@ static void import_endjob(void *user_data) static void import_freejob(void *user_data) { ImportJobData *data = static_cast<ImportJobData *>(user_data); + delete data->archive; delete data; } @@ -886,6 +888,7 @@ bool ABC_import(bContext *C, job->settings.validate_meshes = validate_meshes; job->error_code = ABC_NO_ERROR; job->was_cancelled = false; + job->archive = NULL; G.is_break = false; diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index b991ac24284..257975e3c17 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -29,8 +29,10 @@ extern "C" { #endif struct CacheFile; +struct CacheReader; struct Depsgraph; struct Main; +struct Object; struct Scene; void BKE_cachefiles_init(void); @@ -52,24 +54,27 @@ void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local); -void BKE_cachefile_reload(const struct Main *bmain, struct CacheFile *cache_file); +void BKE_cachefile_reload(struct Depsgraph *depsgraph, struct CacheFile *cache_file); -void BKE_cachefile_ensure_handle(const struct Main *bmain, struct CacheFile *cache_file); - -void BKE_cachefile_update_frame(struct Main *bmain, - struct Depsgraph *depsgraph, - struct Scene *scene, - const float ctime, - const float fps); +void BKE_cachefile_eval(struct Main *bmain, + struct Depsgraph *depsgraph, + struct CacheFile *cache_file); bool BKE_cachefile_filepath_get(const struct Main *bmain, + const struct Depsgraph *depsgrah, const struct CacheFile *cache_file, - float frame, char r_filename[1024]); -float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps); +float BKE_cachefile_time_offset(const struct CacheFile *cache_file, + const float time, + const float fps); -void BKE_cachefile_clean(struct Main *bmain, struct CacheFile *cache_file); +/* Modifiers and constraints open and free readers through these. */ +void BKE_cachefile_reader_open(struct CacheFile *cache_file, + struct CacheReader **reader, + struct Object *object, + const char *object_path); +void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader **reader); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index e4fc4706e66..a60b840344c 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -21,18 +21,21 @@ * \ingroup bke */ +#include <string.h> + #include "DNA_anim_types.h" #include "DNA_cachefile_types.h" #include "DNA_constraint_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" +#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_threads.h" -#include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_cachefile.h" @@ -41,10 +44,13 @@ #include "BKE_modifier.h" #include "BKE_scene.h" +#include "DEG_depsgraph_query.h" + #ifdef WITH_ALEMBIC # include "ABC_alembic.h" #endif +/* TODO: make this per cache file to avoid global locks. */ static SpinLock spin; void BKE_cachefiles_init(void) @@ -57,6 +63,94 @@ void BKE_cachefiles_exit(void) BLI_spin_end(&spin); } +void BKE_cachefile_reader_open(CacheFile *cache_file, + struct CacheReader **reader, + Object *object, + const char *object_path) +{ +#ifdef WITH_ALEMBIC + BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE); + + if (cache_file->handle == NULL) { + return; + } + + /* Open Alembic cache reader. */ + *reader = CacheReader_open_alembic_object(cache_file->handle, *reader, object, object_path); + + /* Multiple modifiers and constraints can call this function concurrently. */ + BLI_spin_lock(&spin); + if (*reader) { + /* Register in set so we can free it when the cache file changes. */ + if (cache_file->handle_readers == NULL) { + cache_file->handle_readers = BLI_gset_ptr_new("CacheFile.handle_readers"); + } + BLI_gset_reinsert(cache_file->handle_readers, reader, NULL); + } + else if (cache_file->handle_readers) { + /* Remove in case CacheReader_open_alembic_object free the existing reader. */ + BLI_gset_remove(cache_file->handle_readers, reader, NULL); + } + BLI_spin_unlock(&spin); +#else + UNUSED_VARS(reader, object, object_path); +#endif +} + +void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reader) +{ +#ifdef WITH_ALEMBIC + BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE); + + if (*reader != NULL) { + CacheReader_free(*reader); + *reader = NULL; + + /* Multiple modifiers and constraints can call this function concurrently. */ + BLI_spin_lock(&spin); + if (cache_file->handle_readers) { + BLI_gset_remove(cache_file->handle_readers, reader, NULL); + } + BLI_spin_unlock(&spin); + } +#else + UNUSED_VARS(cache_file, reader); +#endif +} + +static void cachefile_handle_free(CacheFile *cache_file) +{ +#ifdef WITH_ALEMBIC + /* Free readers in all modifiers and constraints that use the handle, before + * we free the handle itself. */ + BLI_spin_lock(&spin); + if (cache_file->handle_readers) { + GSetIterator gs_iter; + GSET_ITER (gs_iter, cache_file->handle_readers) { + struct CacheReader **reader = BLI_gsetIterator_getKey(&gs_iter); + if (*reader != NULL) { + CacheReader_free(*reader); + *reader = NULL; + } + } + + BLI_gset_free(cache_file->handle_readers, NULL); + cache_file->handle_readers = NULL; + } + BLI_spin_unlock(&spin); + + /* Free handle. */ + if (cache_file->handle) { + ABC_free_handle(cache_file->handle); + cache_file->handle = NULL; + } + + cache_file->handle_filepath[0] = '\0'; +#else + UNUSED_VARS(cache_file); +#endif +} + void *BKE_cachefile_add(Main *bmain, const char *name) { CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name, 0); @@ -68,37 +162,23 @@ void *BKE_cachefile_add(Main *bmain, const char *name) void BKE_cachefile_init(CacheFile *cache_file) { - cache_file->handle = NULL; cache_file->filepath[0] = '\0'; cache_file->override_frame = false; cache_file->frame = 0.0f; cache_file->is_sequence = false; cache_file->scale = 1.0f; - cache_file->handle_mutex = BLI_mutex_alloc(); BLI_listbase_clear(&cache_file->object_paths); + + cache_file->handle = NULL; + cache_file->handle_filepath[0] = '\0'; + cache_file->handle_readers = NULL; } /** Free (or release) any data used by this cachefile (does not free the cachefile itself). */ void BKE_cachefile_free(CacheFile *cache_file) { BKE_animdata_free((ID *)cache_file, false); - - if (cache_file->id.tag & LIB_TAG_NO_MAIN) { - /* CoW/no-main copies reuse the existing ArchiveReader and mutex */ - return; - } - - if (cache_file->handle) { -#ifdef WITH_ALEMBIC - ABC_free_handle(cache_file->handle); -#endif - cache_file->handle = NULL; - } - if (cache_file->handle_mutex) { - BLI_mutex_free(cache_file->handle_mutex); - cache_file->handle_mutex = NULL; - } - + cachefile_handle_free(cache_file); BLI_freelistN(&cache_file->object_paths); } @@ -117,13 +197,8 @@ void BKE_cachefile_copy_data(Main *UNUSED(bmain), const CacheFile *UNUSED(cache_file_src), const int UNUSED(flag)) { - if (cache_file_dst->id.tag & LIB_TAG_NO_MAIN) { - /* CoW/no-main copies reuse the existing ArchiveReader and mutex */ - return; - } - cache_file_dst->handle = NULL; - cache_file_dst->handle_mutex = NULL; + cache_file_dst->handle_readers = NULL; BLI_duplicatelist(&cache_file_dst->object_paths, &cache_file_dst->object_paths); } @@ -139,72 +214,51 @@ void BKE_cachefile_make_local(Main *bmain, CacheFile *cache_file, const bool lib BKE_id_make_local_generic(bmain, &cache_file->id, true, lib_local); } -void BKE_cachefile_reload(const Main *bmain, CacheFile *cache_file) +void BKE_cachefile_reload(Depsgraph *depsgraph, CacheFile *cache_file) { - char filepath[FILE_MAX]; - - BLI_strncpy(filepath, cache_file->filepath, sizeof(filepath)); - BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &cache_file->id)); - -#ifdef WITH_ALEMBIC - if (cache_file->handle) { - ABC_free_handle(cache_file->handle); + /* To force reload, free the handle and tag depsgraph to load it again. */ + CacheFile *cache_file_eval = (CacheFile *)DEG_get_evaluated_id(depsgraph, &cache_file->id); + if (cache_file_eval) { + cachefile_handle_free(cache_file_eval); } - cache_file->handle = ABC_create_handle(filepath, &cache_file->object_paths); -#endif + DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE); } -void BKE_cachefile_ensure_handle(const Main *bmain, CacheFile *cache_file) +void BKE_cachefile_eval(Main *bmain, Depsgraph *depsgraph, CacheFile *cache_file) { - BLI_spin_lock(&spin); - if (cache_file->handle_mutex == NULL) { - cache_file->handle_mutex = BLI_mutex_alloc(); - } - BLI_spin_unlock(&spin); - - BLI_mutex_lock(cache_file->handle_mutex); + BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE); - if (cache_file->handle == NULL) { - /* Assigning to a CoW copy is a bad idea; assign to the original instead. */ - BLI_assert((cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0); - BKE_cachefile_reload(bmain, cache_file); + /* Compute filepath. */ + char filepath[FILE_MAX]; + if (!BKE_cachefile_filepath_get(bmain, depsgraph, cache_file, filepath)) { + return; } - BLI_mutex_unlock(cache_file->handle_mutex); -} - -void BKE_cachefile_update_frame( - Main *bmain, struct Depsgraph *depsgraph, Scene *scene, const float ctime, const float fps) -{ - CacheFile *cache_file; - char filename[FILE_MAX]; - - for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { - /* TODO: dependency graph should be updated to do drivers on cachefile. - * Execute drivers only, as animation has already been done. */ - BKE_animsys_evaluate_animdata( - depsgraph, scene, &cache_file->id, cache_file->adt, ctime, ADT_RECALC_DRIVERS); - - if (!cache_file->is_sequence) { - continue; - } + /* Test if filepath change or if we can keep the existing handle. */ + if (STREQ(cache_file->handle_filepath, filepath)) { + return; + } - const float time = BKE_cachefile_time_offset(cache_file, ctime, fps); + cachefile_handle_free(cache_file); + BLI_freelistN(&cache_file->object_paths); - if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) { - BKE_cachefile_clean(bmain, cache_file); #ifdef WITH_ALEMBIC - ABC_free_handle(cache_file->handle); - cache_file->handle = ABC_create_handle(filename, NULL); + cache_file->handle = ABC_create_handle(filepath, &cache_file->object_paths); + BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX); #endif - } + + if (DEG_is_active(depsgraph)) { + /* Flush object paths back to original datablock for UI. */ + CacheFile *cache_file_orig = (CacheFile *)DEG_get_original_id(&cache_file->id); + BLI_freelistN(&cache_file_orig->object_paths); + BLI_duplicatelist(&cache_file_orig->object_paths, &cache_file->object_paths); } } bool BKE_cachefile_filepath_get(const Main *bmain, + const Depsgraph *depsgraph, const CacheFile *cache_file, - float frame, char r_filepath[FILE_MAX]) { BLI_strncpy(r_filepath, cache_file->filepath, FILE_MAX); @@ -214,6 +268,11 @@ bool BKE_cachefile_filepath_get(const Main *bmain, int frame_len; if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) { + Scene *scene = DEG_get_evaluated_scene(depsgraph); + const float ctime = BKE_scene_frame_get(scene); + const float fps = (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base); + const float frame = BKE_cachefile_time_offset(cache_file, ctime, fps); + char ext[32]; BLI_path_frame_strip(r_filepath, ext); BLI_path_frame(r_filepath, frame, frame_len); @@ -226,47 +285,9 @@ bool BKE_cachefile_filepath_get(const Main *bmain, return true; } -float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const float fps) +float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, const float fps) { const float time_offset = cache_file->frame_offset / fps; const float frame = (cache_file->override_frame ? cache_file->frame : time); return cache_file->is_sequence ? frame : frame / fps - time_offset; } - -/* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */ -void BKE_cachefile_clean(struct Main *bmain, CacheFile *cache_file) -{ - for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { - ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); - - if (md) { - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - if (cache_file == mcmd->cache_file) { -#ifdef WITH_ALEMBIC - if (mcmd->reader != NULL) { - CacheReader_free(mcmd->reader); - } -#endif - mcmd->reader = NULL; - } - } - - for (bConstraint *con = ob->constraints.first; con; con = con->next) { - if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) { - continue; - } - - bTransformCacheConstraint *data = con->data; - - if (cache_file == data->cache_file) { -#ifdef WITH_ALEMBIC - if (data->reader != NULL) { - CacheReader_free(data->reader); - } -#endif - data->reader = NULL; - } - } - } -} diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a475a16dd57..0e29f165992 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4835,13 +4835,9 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa const float frame = DEG_get_ctime(cob->depsgraph); const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); - /* Must always load ABC handle on original. */ - CacheFile *cache_file_orig = (CacheFile *)DEG_get_original_id(&cache_file->id); - BKE_cachefile_ensure_handle(G.main, cache_file_orig); - - if (!data->reader) { - data->reader = CacheReader_open_alembic_object( - cache_file_orig->handle, data->reader, cob->ob, data->object_path); + if (!data->reader || !STREQ(data->reader_object_path, data->object_path)) { + STRNCPY(data->reader_object_path, data->object_path); + BKE_cachefile_reader_open(cache_file, &data->reader, cob->ob, data->object_path); } ABC_get_transform(data->reader, cob->matrix, time, cache_file->scale); @@ -4859,12 +4855,8 @@ static void transformcache_copy(bConstraint *con, bConstraint *srccon) BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path)); dst->cache_file = src->cache_file; - -#ifdef WITH_ALEMBIC - if (dst->reader) { - CacheReader_incref(dst->reader); - } -#endif + dst->reader = NULL; + dst->reader_object_path[0] = '\0'; } static void transformcache_free(bConstraint *con) @@ -4872,10 +4864,8 @@ static void transformcache_free(bConstraint *con) bTransformCacheConstraint *data = con->data; if (data->reader) { -#ifdef WITH_ALEMBIC - CacheReader_free(data->reader); -#endif - data->reader = NULL; + BKE_cachefile_reader_free(data->cache_file, &data->reader); + data->reader_object_path[0] = '\0'; } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index e0bf62402d2..58b36aed24f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1565,15 +1565,6 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain) BKE_image_editors_update_frame(bmain, scene->r.cfra); BKE_sound_set_cfra(scene->r.cfra); DEG_graph_relations_update(depsgraph, bmain, scene, view_layer); - /* Update animated cache files for modifiers. - * - * TODO(sergey): Make this a depsgraph node? - */ - BKE_cachefile_update_frame(bmain, - depsgraph, - scene, - ctime, - (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base)); #ifdef POSE_ANIMATION_WORKAROUND scene_armature_depsgraph_workaround(bmain, depsgraph); #endif diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 55f02b45854..bf96cc9fa8e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3305,7 +3305,8 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) { BLI_listbase_clear(&cache_file->object_paths); cache_file->handle = NULL; - cache_file->handle_mutex = NULL; + cache_file->handle_filepath[0] = '\0'; + cache_file->handle_readers = NULL; /* relink animdata */ cache_file->adt = newdataadr(fd, cache_file->adt); @@ -3739,6 +3740,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb) case CONSTRAINT_TYPE_TRANSFORM_CACHE: { bTransformCacheConstraint *data = con->data; data->reader = NULL; + data->reader_object_path[0] = '\0'; } } } @@ -5745,6 +5747,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) else if (md->type == eModifierType_MeshSequenceCache) { MeshSeqCacheModifierData *msmcd = (MeshSeqCacheModifierData *)md; msmcd->reader = NULL; + msmcd->reader_object_path[0] = '\0'; } else if (md->type == eModifierType_SurfaceDeform) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 87bbcef7f01..b6822a89093 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -65,6 +65,7 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_animsys.h" +#include "BKE_cachefile.h" #include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_curve.h" @@ -1469,11 +1470,16 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file) return; } ID *cache_file_id = &cache_file->id; + add_id_node(cache_file_id); + CacheFile *cache_file_cow = get_cow_datablock(cache_file); /* Animation, */ build_animdata(cache_file_id); build_parameters(cache_file_id); /* Cache evaluation itself. */ - add_operation_node(cache_file_id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE); + add_operation_node(cache_file_id, + NodeType::CACHE, + OperationCode::FILE_CACHE_UPDATE, + function_bind(BKE_cachefile_eval, bmain_, _1, cache_file_cow)); } void DepsgraphNodeBuilder::build_mask(Mask *mask) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 147d82c5999..d3fd16d889f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -2222,6 +2222,14 @@ void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file) ComponentKey datablock_key(&cache_file->id, NodeType::CACHE); add_relation(animation_key, datablock_key, "Datablock Animation"); } + + /* Cache file updates */ + if (cache_file->is_sequence) { + OperationKey cache_update_key( + &cache_file->id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE); + TimeSourceKey time_src_key; + add_relation(time_src_key, cache_update_key, "TimeSrc -> Cache File Eval"); + } } void DepsgraphRelationBuilder::build_mask(Mask *mask) @@ -2329,7 +2337,8 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) continue; } int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE); - if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) { + if ((id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) || + (id_type == ID_CF && comp_node->type == NodeType::CACHE)) { rel_flag &= ~RELATION_FLAG_NO_FLUSH; } /* Notes on exceptions: diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index f656e917c44..e96141eaa05 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -6711,17 +6711,18 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE); row = uiLayoutRow(layout, false); - uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame")); + uiLayoutSetActive(row, RNA_boolean_get(&fileptr, "override_frame")); uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE); row = uiLayoutRow(layout, false); uiItemR(row, &fileptr, "frame_offset", 0, "Frame Offset", ICON_NONE); + uiLayoutSetActive(row, !RNA_boolean_get(&fileptr, "is_sequence")); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiLayoutSetEnabled(row, (sbuts->mainb == BCONTEXT_CONSTRAINT)); + uiLayoutSetActive(row, (sbuts->mainb == BCONTEXT_CONSTRAINT)); uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE); /* TODO: unused for now, so no need to expose. */ diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index 6358c2c1370..3dd3b20bda3 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -38,6 +38,8 @@ #include "RNA_access.h" +#include "DEG_depsgraph.h" + #include "UI_interface.h" #include "WM_api.h" @@ -93,7 +95,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op) CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0); BLI_strncpy(cache_file->filepath, filename, FILE_MAX); - BKE_cachefile_reload(bmain, cache_file); + DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE); /* Will be set when running invoke, not exec directly. */ if (op->customdata != NULL) { @@ -137,7 +139,7 @@ void CACHEFILE_OT_open(wmOperatorType *ot) /* ***************************** Reload Operator **************************** */ -static int cachefile_reload_exec(bContext *C, wmOperator *op) +static int cachefile_reload_exec(bContext *C, wmOperator *UNUSED(op)) { CacheFile *cache_file = CTX_data_edit_cachefile(C); @@ -145,14 +147,10 @@ static int cachefile_reload_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - Main *bmain = CTX_data_main(C); - - BLI_freelistN(&cache_file->object_paths); - BKE_cachefile_reload(bmain, cache_file); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + BKE_cachefile_reload(depsgraph, cache_file); return OPERATOR_FINISHED; - - UNUSED_VARS(op); } void CACHEFILE_OT_reload(wmOperatorType *ot) diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h index e5f77f70720..bc57202367c 100644 --- a/source/blender/makesdna/DNA_cachefile_types.h +++ b/source/blender/makesdna/DNA_cachefile_types.h @@ -30,10 +30,12 @@ extern "C" { #endif +struct GSet; + /* CacheFile::flag */ enum { CACHEFILE_DS_EXPAND = (1 << 0), - CACHEFILE_DIRTY = (1 << 1), + CACHEFILE_UNUSED_0 = (1 << 1), }; /* CacheFile::draw_flag */ @@ -53,9 +55,6 @@ typedef struct CacheFile { ID id; struct AnimData *adt; - struct AbcArchiveHandle *handle; - void *handle_mutex; - /** Paths of the objects inside of the Alembic archive referenced by this CacheFile. */ ListBase object_paths; @@ -78,6 +77,11 @@ typedef struct CacheFile { short draw_flag; char _pad[4]; + + /* Runtime */ + struct AbcArchiveHandle *handle; + char handle_filepath[1024]; + struct GSet *handle_readers; } CacheFile; #ifdef __cplusplus diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 3ca61400e2e..f839f22ec9f 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -593,9 +593,12 @@ typedef struct bObjectSolverConstraint { /* Transform matrix cache constraint */ typedef struct bTransformCacheConstraint { struct CacheFile *cache_file; - struct CacheReader *reader; /** FILE_MAX. */ char object_path[1024]; + + /* Runtime. */ + struct CacheReader *reader; + char reader_object_path[1024]; } bTransformCacheConstraint; /* ------------------------------------------ */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 1b85fb26c0e..6a524e03b6e 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1852,12 +1852,15 @@ typedef struct MeshSeqCacheModifierData { ModifierData modifier; struct CacheFile *cache_file; - struct CacheReader *reader; /** 1024 = FILE_MAX. */ char object_path[1024]; char read_flag; char _pad[7]; + + /* Runtime. */ + struct CacheReader *reader; + char reader_object_path[1024]; } MeshSeqCacheModifierData; /* MeshSeqCacheModifierData.read_flag */ diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c index fb61be69ee6..189a4a7de86 100644 --- a/source/blender/makesrna/intern/rna_cachefile.c +++ b/source/blender/makesrna/intern/rna_cachefile.c @@ -45,29 +45,12 @@ # include "../../../alembic/ABC_alembic.h" # endif -static void rna_CacheFile_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_CacheFile_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { CacheFile *cache_file = (CacheFile *)ptr->data; - DEG_id_tag_update(&cache_file->id, 0); + DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); - - UNUSED_VARS(bmain, scene); -} - -static void rna_CacheFile_update_handle(Main *bmain, Scene *scene, PointerRNA *ptr) -{ - CacheFile *cache_file = ptr->data; - - if ((cache_file->flag & CACHEFILE_DIRTY) != 0) { - BKE_cachefile_clean(bmain, cache_file); - BLI_freelistN(&cache_file->object_paths); - cache_file->flag &= ~CACHEFILE_DIRTY; - } - - BKE_cachefile_reload(bmain, cache_file); - - rna_CacheFile_update(bmain, scene, ptr); } static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) @@ -76,20 +59,6 @@ static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, P rna_iterator_listbase_begin(iter, &cache_file->object_paths, NULL); } -static void rna_CacheFile_filename_set(PointerRNA *ptr, const char *value) -{ - CacheFile *cache_file = ptr->data; - - if (STREQ(cache_file->filepath, value)) { - return; - } - - /* Different file is opened, close all readers. */ - cache_file->flag |= CACHEFILE_DIRTY; - - BLI_strncpy(cache_file->filepath, value, sizeof(cache_file->filepath)); -} - #else /* cachefile.object_paths */ @@ -122,9 +91,8 @@ static void rna_def_cachefile(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_FILE); PropertyRNA *prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); - RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CacheFile_filename_set"); RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file"); - RNA_def_property_update(prop, 0, "rna_CacheFile_update_handle"); + RNA_def_property_update(prop, 0, "rna_CacheFile_update"); prop = RNA_def_property(srna, "is_sequence", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 44445181402..c1c235d497b 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -729,22 +729,6 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, PointerRNA v } } -static void rna_Constraint_transformCache_object_path_update(Main *bmain, - Scene *scene, - PointerRNA *ptr) -{ -# ifdef WITH_ALEMBIC - bConstraint *con = (bConstraint *)ptr->data; - bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data; - Object *ob = (Object *)ptr->id.data; - - data->reader = CacheReader_open_alembic_object( - data->cache_file->handle, data->reader, ob, data->object_path); -# endif - - rna_Constraint_update(bmain, scene, ptr); -} - #else static const EnumPropertyItem constraint_distance_items[] = { @@ -2902,7 +2886,7 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna) prop, "Object Path", "Path to the object in the Alembic archive used to lookup the transform matrix"); - RNA_def_property_update(prop, 0, "rna_Constraint_transformCache_object_path_update"); + RNA_def_property_update(prop, 0, "rna_Constraint_update"); } /* base struct for constraints */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 8a63bf1a619..4f304f97cac 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1300,19 +1300,6 @@ static bool rna_SurfaceDeformModifier_is_bound_get(PointerRNA *ptr) return (((SurfaceDeformModifierData *)ptr->data)->verts != NULL); } -static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene, PointerRNA *ptr) -{ -# ifdef WITH_ALEMBIC - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)ptr->data; - Object *ob = (Object *)ptr->id.data; - - mcmd->reader = CacheReader_open_alembic_object( - mcmd->cache_file->handle, mcmd->reader, ob, mcmd->object_path); -# endif - - rna_Modifier_update(bmain, scene, ptr); -} - static bool rna_ParticleInstanceModifier_particle_system_poll(PointerRNA *ptr, const PointerRNA value) { @@ -5107,7 +5094,7 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna) prop, "Object Path", "Path to the object in the Alembic archive used to lookup geometric data"); - RNA_def_property_update(prop, 0, "rna_MeshSequenceCache_object_path_update"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); static const EnumPropertyItem read_flag_items[] = { {MOD_MESHSEQ_READ_VERT, "VERT", 0, "Vertex", ""}, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 7710082150b..760830ffb24 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -18,6 +18,11 @@ * \ingroup modifiers */ +#include <string.h> + +#include "BLI_utildefines.h" +#include "BLI_string.h" + #include "DNA_cachefile_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -47,6 +52,9 @@ static void initData(ModifierData *md) mcmd->cache_file = NULL; mcmd->object_path[0] = '\0'; mcmd->read_flag = MOD_MESHSEQ_READ_ALL; + + mcmd->reader = NULL; + mcmd->reader_object_path[0] = '\0'; } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -59,6 +67,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla modifier_copyData_generic(md, target, flag); tmcmd->reader = NULL; + tmcmd->reader_object_path[0] = '\0'; } static void freeData(ModifierData *md) @@ -66,10 +75,8 @@ static void freeData(ModifierData *md) MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; if (mcmd->reader) { -#ifdef WITH_ALEMBIC - CacheReader_free(mcmd->reader); -#endif - mcmd->reader = NULL; + mcmd->reader_object_path[0] = '\0'; + BKE_cachefile_reader_free(mcmd->cache_file, &mcmd->reader); } } @@ -93,17 +100,14 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes 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(mcmd->cache_file, frame, FPS); + const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); const char *err_str = NULL; - CacheFile *cache_file = (CacheFile *)DEG_get_original_id(&mcmd->cache_file->id); - - BKE_cachefile_ensure_handle(G.main, cache_file); - - if (!mcmd->reader) { - mcmd->reader = CacheReader_open_alembic_object( - cache_file->handle, NULL, ctx->object, mcmd->object_path); + 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) { modifier_setError(md, "Could not create Alembic reader for file %s", cache_file->filepath); return mesh; |