diff --git a/source/blender/blenkernel/BKE_simulation_state.hh b/source/blender/blenkernel/BKE_simulation_state.hh index c72a50c3568..63d514d3a91 100644 --- a/source/blender/blenkernel/BKE_simulation_state.hh +++ b/source/blender/blenkernel/BKE_simulation_state.hh @@ -162,7 +162,7 @@ class ModifierSimulationCache { CacheState cache_state_ = CacheState::Valid; bool failed_finding_bake_ = false; - void try_discover_bake(StringRefNull meta_dir, StringRefNull bdata_dir); + void try_discover_bake(StringRefNull absolute_bake_dir); bool has_state_at_frame(const SubFrame &frame) const; bool has_states() const; diff --git a/source/blender/blenkernel/BKE_simulation_state_serialize.hh b/source/blender/blenkernel/BKE_simulation_state_serialize.hh index d9cfc773514..8ad6b64a5b3 100644 --- a/source/blender/blenkernel/BKE_simulation_state_serialize.hh +++ b/source/blender/blenkernel/BKE_simulation_state_serialize.hh @@ -143,12 +143,11 @@ class DiskBDataWriter : public BDataWriter { }; /** - * Get the directory that contains all baked simulation data for the given modifier. This is a - * parent directory of the two directories below. + * Get the directory that contains all baked simulation data for the given modifier. */ -std::string get_bake_directory(const Main &bmain, const Object &object, const ModifierData &md); -std::string get_bdata_directory(const Main &bmain, const Object &object, const ModifierData &md); -std::string get_meta_directory(const Main &bmain, const Object &object, const ModifierData &md); +std::string get_default_modifier_bake_directory(const Main &bmain, + const Object &object, + const ModifierData &md); /** * Encode the simulation state in a #DictionaryValue which also contains references to external diff --git a/source/blender/blenkernel/intern/simulation_state.cc b/source/blender/blenkernel/intern/simulation_state.cc index c66a8b7aa8e..ced43350276 100644 --- a/source/blender/blenkernel/intern/simulation_state.cc +++ b/source/blender/blenkernel/intern/simulation_state.cc @@ -37,19 +37,24 @@ StringSimulationStateItem::StringSimulationStateItem(std::string value) : value_ { } -void ModifierSimulationCache::try_discover_bake(const StringRefNull meta_dir, - const StringRefNull bdata_dir) +void ModifierSimulationCache::try_discover_bake(const StringRefNull absolute_bake_dir) { if (failed_finding_bake_) { return; } - if (!BLI_is_dir(meta_dir.c_str()) || !BLI_is_dir(bdata_dir.c_str())) { + + char meta_dir[FILE_MAX]; + BLI_path_join(meta_dir, sizeof(meta_dir), absolute_bake_dir.c_str(), "meta"); + char bdata_dir[FILE_MAX]; + BLI_path_join(bdata_dir, sizeof(bdata_dir), absolute_bake_dir.c_str(), "bdata"); + + if (!BLI_is_dir(meta_dir) || !BLI_is_dir(bdata_dir)) { failed_finding_bake_ = true; return; } direntry *dir_entries = nullptr; - const int dir_entries_num = BLI_filelist_dir_contents(meta_dir.c_str(), &dir_entries); + const int dir_entries_num = BLI_filelist_dir_contents(meta_dir, &dir_entries); BLI_SCOPED_DEFER([&]() { BLI_filelist_free(dir_entries, dir_entries_num); }); if (dir_entries_num == 0) { diff --git a/source/blender/blenkernel/intern/simulation_state_serialize.cc b/source/blender/blenkernel/intern/simulation_state_serialize.cc index 070ca85901d..4a51983228c 100644 --- a/source/blender/blenkernel/intern/simulation_state_serialize.cc +++ b/source/blender/blenkernel/intern/simulation_state_serialize.cc @@ -42,26 +42,18 @@ static std::string escape_name(const StringRef name) return ss.str(); } -static std::string get_blendcache_directory(const Main &bmain) +static std::string get_blend_file_name(const Main &bmain) { - StringRefNull blend_file_path = BKE_main_blendfile_path(&bmain); - char blend_directory[FILE_MAX]; + const StringRefNull blend_file_path = BKE_main_blendfile_path(&bmain); char blend_name[FILE_MAX]; - BLI_path_split_dir_file(blend_file_path.c_str(), - blend_directory, - sizeof(blend_directory), - blend_name, - sizeof(blend_name)); + + BLI_path_split_file_part(blend_file_path.c_str(), blend_name, sizeof(blend_name)); const int64_t type_start_index = StringRef(blend_name).rfind("."); if (type_start_index == StringRef::not_found) { return ""; } blend_name[type_start_index] = '\0'; - const std::string blendcache_name = "blendcache_" + StringRef(blend_name); - - char blendcache_dir[FILE_MAX]; - BLI_path_join(blendcache_dir, sizeof(blendcache_dir), blend_directory, blendcache_name.c_str()); - return blendcache_dir; + return "blendcache_" + StringRef(blend_name); } static std::string get_modifier_sim_name(const Object &object, const ModifierData &md) @@ -71,29 +63,18 @@ static std::string get_modifier_sim_name(const Object &object, const ModifierDat return "sim_" + object_name_escaped + "_" + modifier_name_escaped; } -std::string get_bake_directory(const Main &bmain, const Object &object, const ModifierData &md) +std::string get_default_modifier_bake_directory(const Main &bmain, + const Object &object, + const ModifierData &md) { - char bdata_dir[FILE_MAX]; - BLI_path_join(bdata_dir, - sizeof(bdata_dir), - get_blendcache_directory(bmain).c_str(), + char dir[FILE_MAX]; + /* Make path that's relative to the .blend file. */ + BLI_path_join(dir, + sizeof(dir), + "//", + get_blend_file_name(bmain).c_str(), get_modifier_sim_name(object, md).c_str()); - return bdata_dir; -} - -std::string get_bdata_directory(const Main &bmain, const Object &object, const ModifierData &md) -{ - char bdata_dir[FILE_MAX]; - BLI_path_join( - bdata_dir, sizeof(bdata_dir), get_bake_directory(bmain, object, md).c_str(), "bdata"); - return bdata_dir; -} - -std::string get_meta_directory(const Main &bmain, const Object &object, const ModifierData &md) -{ - char meta_dir[FILE_MAX]; - BLI_path_join(meta_dir, sizeof(meta_dir), get_bake_directory(bmain, object, md).c_str(), "meta"); - return meta_dir; + return dir; } std::shared_ptr BDataSlice::serialize() const diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index b34bee27a6a..ee9b20f9cdf 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -67,6 +67,7 @@ #include "BKE_modifier.h" #include "BKE_node.hh" #include "BKE_screen.h" +#include "BKE_simulation_state_serialize.hh" #include "BKE_workspace.h" #include "RNA_access.h" @@ -4483,5 +4484,21 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) /* Keep this block, even when empty. */ BKE_animdata_main_cb(bmain, version_liboverride_nla_frame_start_end, NULL); + + /* Store simulation bake directory in geometry nodes modifier. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type != eModifierType_Nodes) { + continue; + } + NodesModifierData *nmd = reinterpret_cast(md); + if (nmd->simulation_bake_directory) { + continue; + } + const std::string bake_dir = blender::bke::sim::get_default_modifier_bake_directory( + *bmain, *ob, *md); + nmd->simulation_bake_directory = BLI_strdup(bake_dir.c_str()); + } + } } } diff --git a/source/blender/editors/object/object_bake_simulation.cc b/source/blender/editors/object/object_bake_simulation.cc index ef85a05370d..1ae4479e565 100644 --- a/source/blender/editors/object/object_bake_simulation.cc +++ b/source/blender/editors/object/object_bake_simulation.cc @@ -209,8 +209,7 @@ static bool bake_simulation_poll(bContext *C) struct ModifierBakeData { NodesModifierData *nmd; - std::string meta_dir; - std::string bdata_dir; + std::string absolute_bake_dir; std::unique_ptr bdata_sharing; }; @@ -244,6 +243,9 @@ static void bake_simulation_job_startjob(void *customdata, if (!BKE_id_is_editable(job.bmain, &object->id)) { continue; } + + const char *base_path = ID_BLEND_PATH(job.bmain, &object->id); + ObjectBakeData bake_data; bake_data.object = object; LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { @@ -252,10 +254,14 @@ static void bake_simulation_job_startjob(void *customdata, if (nmd->simulation_cache != nullptr) { nmd->simulation_cache->reset(); } - bake_data.modifiers.append({nmd, - bke::sim::get_meta_directory(*job.bmain, *object, *md), - bke::sim::get_bdata_directory(*job.bmain, *object, *md), - std::make_unique()}); + if (StringRef(nmd->simulation_bake_directory).is_empty()) { + nmd->simulation_bake_directory = BLI_strdup( + bke::sim::get_default_modifier_bake_directory(*job.bmain, *object, *md).c_str()); + } + char absolute_bake_dir[FILE_MAX]; + STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory); + BLI_path_abs(absolute_bake_dir, base_path); + bake_data.modifiers.append({nmd, absolute_bake_dir, std::make_unique()}); } } objects_to_bake.append(std::move(bake_data)); @@ -305,12 +311,14 @@ static void bake_simulation_job_startjob(void *customdata, char bdata_path[FILE_MAX]; BLI_path_join(bdata_path, sizeof(bdata_path), - modifier_bake_data.bdata_dir.c_str(), + modifier_bake_data.absolute_bake_dir.c_str(), + "bdata", bdata_file_name.c_str()); char meta_path[FILE_MAX]; BLI_path_join(meta_path, sizeof(meta_path), - modifier_bake_data.meta_dir.c_str(), + modifier_bake_data.absolute_bake_dir.c_str(), + "meta", meta_file_name.c_str()); BLI_file_ensure_parent_dir_exists(bdata_path); @@ -429,21 +437,25 @@ static int delete_baked_simulation_exec(bContext *C, wmOperator *op) } for (Object *object : objects) { + const char *base_path = ID_BLEND_PATH(bmain, &object->id); LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { if (md->type == eModifierType_Nodes) { NodesModifierData *nmd = reinterpret_cast(md); - const std::string bake_directory = bke::sim::get_bake_directory(*bmain, *object, *md); - if (BLI_exists(bake_directory.c_str())) { - if (BLI_delete(bake_directory.c_str(), true, true)) { - BKE_reportf(op->reports, - RPT_ERROR, - "Failed to remove bake directory %s", - bake_directory.c_str()); - } - } if (nmd->simulation_cache != nullptr) { nmd->simulation_cache->reset(); } + if (StringRef(nmd->simulation_bake_directory).is_empty()) { + continue; + } + char absolute_bake_dir[FILE_MAX]; + STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory); + BLI_path_abs(absolute_bake_dir, base_path); + if (BLI_exists(absolute_bake_dir)) { + if (BLI_delete(absolute_bake_dir, true, true)) { + BKE_reportf( + op->reports, RPT_ERROR, "Failed to remove bake directory %s", absolute_bake_dir); + } + } } } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 1fb67802460..880efc4b41d 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2319,6 +2319,11 @@ typedef struct NodesModifierData { ModifierData modifier; struct bNodeTree *node_group; struct NodesModifierSettings settings; + /** + * Directory where baked simulation states are stored. This may be relative to the .blend file. + */ + char *simulation_bake_directory; + void *_pad; /** * Contains logged information from the last evaluation. diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 08b9bc3c664..19f9dbace86 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -15,6 +15,7 @@ #include "BLI_listbase.h" #include "BLI_math_vector_types.hh" #include "BLI_multi_value_map.hh" +#include "BLI_path_util.h" #include "BLI_set.hh" #include "BLI_string.h" #include "BLI_string_search.h" @@ -1152,9 +1153,14 @@ static void prepare_simulation_states_for_evaluation(const NodesModifierData &nm if (nmd_orig.simulation_cache->cache_state() != bke::sim::CacheState::Baked && !bmain_path.is_empty()) { - nmd_orig.simulation_cache->try_discover_bake( - bke::sim::get_meta_directory(*bmain, *ctx.object, nmd.modifier), - bke::sim::get_bdata_directory(*bmain, *ctx.object, nmd.modifier)); + if (!StringRef(nmd.simulation_bake_directory).is_empty()) { + if (const char *base_path = ID_BLEND_PATH(bmain, &ctx.object->id)) { + char absolute_bake_dir[FILE_MAX]; + STRNCPY(absolute_bake_dir, nmd.simulation_bake_directory); + BLI_path_abs(absolute_bake_dir, base_path); + nmd_orig.simulation_cache->try_discover_bake(absolute_bake_dir); + } + } } } @@ -1995,6 +2001,8 @@ static void blendWrite(BlendWriter *writer, const ID * /*id_owner*/, const Modif BLO_write_struct(writer, NodesModifierData, nmd); + BLO_write_string(writer, nmd->simulation_bake_directory); + if (nmd->settings.properties != nullptr) { Map boolean_props; if (!BLO_write_is_undo(writer)) { @@ -2033,6 +2041,7 @@ static void blendWrite(BlendWriter *writer, const ID * /*id_owner*/, const Modif static void blendRead(BlendDataReader *reader, ModifierData *md) { NodesModifierData *nmd = reinterpret_cast(md); + BLO_read_data_address(reader, &nmd->simulation_bake_directory); if (nmd->node_group == nullptr) { nmd->settings.properties = nullptr; } @@ -2053,6 +2062,9 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tnmd->runtime_eval_log = nullptr; tnmd->simulation_cache = nullptr; + tnmd->simulation_bake_directory = nmd->simulation_bake_directory ? + BLI_strdup(nmd->simulation_bake_directory) : + nullptr; if (nmd->settings.properties != nullptr) { tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag); @@ -2068,6 +2080,7 @@ static void freeData(ModifierData *md) } MEM_delete(nmd->simulation_cache); + MEM_SAFE_FREE(nmd->simulation_bake_directory); clear_runtime_data(nmd); }