Geometry Nodes: store path to simulation bake in modifier #108201
|
@ -162,7 +162,7 @@ class ModifierSimulationCache {
|
||||||
CacheState cache_state_ = CacheState::Valid;
|
CacheState cache_state_ = CacheState::Valid;
|
||||||
bool failed_finding_bake_ = false;
|
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_state_at_frame(const SubFrame &frame) const;
|
||||||
bool has_states() const;
|
bool has_states() const;
|
||||||
|
|
|
@ -143,12 +143,11 @@ class DiskBDataWriter : public BDataWriter {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the directory that contains all baked simulation data for the given modifier. This is a
|
* Get the directory that contains all baked simulation data for the given modifier.
|
||||||
* parent directory of the two directories below.
|
|
||||||
*/
|
*/
|
||||||
std::string get_bake_directory(const Main &bmain, const Object &object, const ModifierData &md);
|
std::string get_default_modifier_bake_directory(const Main &bmain,
|
||||||
std::string get_bdata_directory(const Main &bmain, const Object &object, const ModifierData &md);
|
const Object &object,
|
||||||
std::string get_meta_directory(const Main &bmain, const Object &object, const ModifierData &md);
|
const ModifierData &md);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the simulation state in a #DictionaryValue which also contains references to external
|
* Encode the simulation state in a #DictionaryValue which also contains references to external
|
||||||
|
|
|
@ -37,19 +37,24 @@ StringSimulationStateItem::StringSimulationStateItem(std::string value) : value_
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModifierSimulationCache::try_discover_bake(const StringRefNull meta_dir,
|
void ModifierSimulationCache::try_discover_bake(const StringRefNull absolute_bake_dir)
|
||||||
const StringRefNull bdata_dir)
|
|
||||||
{
|
{
|
||||||
if (failed_finding_bake_) {
|
if (failed_finding_bake_) {
|
||||||
return;
|
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;
|
failed_finding_bake_ = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
direntry *dir_entries = nullptr;
|
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); });
|
BLI_SCOPED_DEFER([&]() { BLI_filelist_free(dir_entries, dir_entries_num); });
|
||||||
|
|
||||||
if (dir_entries_num == 0) {
|
if (dir_entries_num == 0) {
|
||||||
|
|
|
@ -42,26 +42,18 @@ static std::string escape_name(const StringRef name)
|
||||||
return ss.str();
|
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);
|
const StringRefNull blend_file_path = BKE_main_blendfile_path(&bmain);
|
||||||
char blend_directory[FILE_MAX];
|
|
||||||
char blend_name[FILE_MAX];
|
char blend_name[FILE_MAX];
|
||||||
BLI_path_split_dir_file(blend_file_path.c_str(),
|
|
||||||
blend_directory,
|
BLI_path_split_file_part(blend_file_path.c_str(), blend_name, sizeof(blend_name));
|
||||||
sizeof(blend_directory),
|
|
||||||
blend_name,
|
|
||||||
sizeof(blend_name));
|
|
||||||
const int64_t type_start_index = StringRef(blend_name).rfind(".");
|
const int64_t type_start_index = StringRef(blend_name).rfind(".");
|
||||||
if (type_start_index == StringRef::not_found) {
|
if (type_start_index == StringRef::not_found) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
blend_name[type_start_index] = '\0';
|
blend_name[type_start_index] = '\0';
|
||||||
const std::string blendcache_name = "blendcache_" + StringRef(blend_name);
|
return "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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string get_modifier_sim_name(const Object &object, const ModifierData &md)
|
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;
|
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];
|
char dir[FILE_MAX];
|
||||||
BLI_path_join(bdata_dir,
|
/* Make path that's relative to the .blend file. */
|
||||||
sizeof(bdata_dir),
|
BLI_path_join(dir,
|
||||||
get_blendcache_directory(bmain).c_str(),
|
sizeof(dir),
|
||||||
|
"//",
|
||||||
|
get_blend_file_name(bmain).c_str(),
|
||||||
get_modifier_sim_name(object, md).c_str());
|
get_modifier_sim_name(object, md).c_str());
|
||||||
return bdata_dir;
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<DictionaryValue> BDataSlice::serialize() const
|
std::shared_ptr<DictionaryValue> BDataSlice::serialize() const
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#include "BKE_modifier.h"
|
#include "BKE_modifier.h"
|
||||||
#include "BKE_node.hh"
|
#include "BKE_node.hh"
|
||||||
#include "BKE_screen.h"
|
#include "BKE_screen.h"
|
||||||
|
#include "BKE_simulation_state_serialize.hh"
|
||||||
#include "BKE_workspace.h"
|
#include "BKE_workspace.h"
|
||||||
|
|
||||||
#include "RNA_access.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. */
|
/* Keep this block, even when empty. */
|
||||||
|
|
||||||
BKE_animdata_main_cb(bmain, version_liboverride_nla_frame_start_end, NULL);
|
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<NodesModifierData *>(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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,8 +209,7 @@ static bool bake_simulation_poll(bContext *C)
|
||||||
|
|
||||||
struct ModifierBakeData {
|
struct ModifierBakeData {
|
||||||
NodesModifierData *nmd;
|
NodesModifierData *nmd;
|
||||||
std::string meta_dir;
|
std::string absolute_bake_dir;
|
||||||
std::string bdata_dir;
|
|
||||||
std::unique_ptr<bke::sim::BDataSharing> bdata_sharing;
|
std::unique_ptr<bke::sim::BDataSharing> bdata_sharing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -244,6 +243,9 @@ static void bake_simulation_job_startjob(void *customdata,
|
||||||
if (!BKE_id_is_editable(job.bmain, &object->id)) {
|
if (!BKE_id_is_editable(job.bmain, &object->id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *base_path = ID_BLEND_PATH(job.bmain, &object->id);
|
||||||
|
|
||||||
ObjectBakeData bake_data;
|
ObjectBakeData bake_data;
|
||||||
bake_data.object = object;
|
bake_data.object = object;
|
||||||
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
||||||
|
@ -252,10 +254,14 @@ static void bake_simulation_job_startjob(void *customdata,
|
||||||
if (nmd->simulation_cache != nullptr) {
|
if (nmd->simulation_cache != nullptr) {
|
||||||
nmd->simulation_cache->reset();
|
nmd->simulation_cache->reset();
|
||||||
}
|
}
|
||||||
bake_data.modifiers.append({nmd,
|
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
|
||||||
bke::sim::get_meta_directory(*job.bmain, *object, *md),
|
nmd->simulation_bake_directory = BLI_strdup(
|
||||||
bke::sim::get_bdata_directory(*job.bmain, *object, *md),
|
bke::sim::get_default_modifier_bake_directory(*job.bmain, *object, *md).c_str());
|
||||||
std::make_unique<BDataSharing>()});
|
}
|
||||||
|
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<BDataSharing>()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objects_to_bake.append(std::move(bake_data));
|
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];
|
char bdata_path[FILE_MAX];
|
||||||
BLI_path_join(bdata_path,
|
BLI_path_join(bdata_path,
|
||||||
sizeof(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());
|
bdata_file_name.c_str());
|
||||||
char meta_path[FILE_MAX];
|
char meta_path[FILE_MAX];
|
||||||
BLI_path_join(meta_path,
|
BLI_path_join(meta_path,
|
||||||
sizeof(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());
|
meta_file_name.c_str());
|
||||||
|
|
||||||
BLI_file_ensure_parent_dir_exists(bdata_path);
|
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) {
|
for (Object *object : objects) {
|
||||||
|
const char *base_path = ID_BLEND_PATH(bmain, &object->id);
|
||||||
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
||||||
if (md->type == eModifierType_Nodes) {
|
if (md->type == eModifierType_Nodes) {
|
||||||
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(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) {
|
if (nmd->simulation_cache != nullptr) {
|
||||||
nmd->simulation_cache->reset();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2319,6 +2319,11 @@ typedef struct NodesModifierData {
|
||||||
ModifierData modifier;
|
ModifierData modifier;
|
||||||
struct bNodeTree *node_group;
|
struct bNodeTree *node_group;
|
||||||
struct NodesModifierSettings settings;
|
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.
|
* Contains logged information from the last evaluation.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_math_vector_types.hh"
|
#include "BLI_math_vector_types.hh"
|
||||||
#include "BLI_multi_value_map.hh"
|
#include "BLI_multi_value_map.hh"
|
||||||
|
#include "BLI_path_util.h"
|
||||||
#include "BLI_set.hh"
|
#include "BLI_set.hh"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
#include "BLI_string_search.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 &&
|
if (nmd_orig.simulation_cache->cache_state() != bke::sim::CacheState::Baked &&
|
||||||
!bmain_path.is_empty())
|
!bmain_path.is_empty())
|
||||||
{
|
{
|
||||||
nmd_orig.simulation_cache->try_discover_bake(
|
if (!StringRef(nmd.simulation_bake_directory).is_empty()) {
|
||||||
bke::sim::get_meta_directory(*bmain, *ctx.object, nmd.modifier),
|
if (const char *base_path = ID_BLEND_PATH(bmain, &ctx.object->id)) {
|
||||||
bke::sim::get_bdata_directory(*bmain, *ctx.object, nmd.modifier));
|
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_struct(writer, NodesModifierData, nmd);
|
||||||
|
|
||||||
|
BLO_write_string(writer, nmd->simulation_bake_directory);
|
||||||
|
|
||||||
if (nmd->settings.properties != nullptr) {
|
if (nmd->settings.properties != nullptr) {
|
||||||
Map<IDProperty *, IDPropertyUIDataBool *> boolean_props;
|
Map<IDProperty *, IDPropertyUIDataBool *> boolean_props;
|
||||||
if (!BLO_write_is_undo(writer)) {
|
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)
|
static void blendRead(BlendDataReader *reader, ModifierData *md)
|
||||||
{
|
{
|
||||||
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||||
|
BLO_read_data_address(reader, &nmd->simulation_bake_directory);
|
||||||
if (nmd->node_group == nullptr) {
|
if (nmd->node_group == nullptr) {
|
||||||
nmd->settings.properties = 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->runtime_eval_log = nullptr;
|
||||||
tnmd->simulation_cache = 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) {
|
if (nmd->settings.properties != nullptr) {
|
||||||
tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag);
|
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_delete(nmd->simulation_cache);
|
||||||
|
MEM_SAFE_FREE(nmd->simulation_bake_directory);
|
||||||
|
|
||||||
clear_runtime_data(nmd);
|
clear_runtime_data(nmd);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue