76 G.is_rendering =
true;
93 for (
auto item : nmd->
runtime->cache->simulation_cache_by_id.items()) {
99 objects_to_calc.
append(
object);
105 const float frame_step_size = 1.0f;
106 const float progress_per_frame = 1.0f /
113 if (
G.is_break || worker_status->
stop) {
122 worker_status->
progress += progress_per_frame;
137 G.is_rendering =
false;
173 "Calculating simulation...",
206 if (!use_frame_cache) {
220 std::optional<bake::BakePath>
path;
254 request.
nmd->
runtime->cache->requested_bakes.clear();
261 G.is_rendering =
true;
268 global_bake_start_frame = std::min(global_bake_start_frame, request.
frame_start);
269 global_bake_end_frame = std::max(global_bake_end_frame, request.
frame_end);
275 const int frames_to_bake = global_bake_end_frame - global_bake_start_frame + 1;
277 const float frame_step_size = 1.0f;
278 const float progress_per_frame = frame_step_size / frames_to_bake;
281 struct MemoryBakeFile {
294 for (
float frame_f = global_bake_start_frame; frame_f <= global_bake_end_frame;
295 frame_f += frame_step_size)
299 if (
G.is_break || worker_status->
stop) {
318 if (bake_cache ==
nullptr) {
321 if (bake_cache->
frames.is_empty()) {
325 if (frame_cache.
frame != frame) {
331 if (request.
path.has_value()) {
335 request.
path->meta_dir.c_str(),
336 (frame_file_name +
".json").c_str());
339 fstream meta_file{meta_path, std::ios::out};
342 written_size += meta_file.tellp();
348 std::ostringstream meta_file{std::ios::binary};
351 packed_data.meta_files.append({frame_file_name +
".json", meta_file.str()});
354 for (
auto &&item : blob_stream_by_name.
items()) {
355 std::string
data = item.value.stream->str();
363 packed_data.blob_files.append({item.key, std::move(
data)});
366 written_size += meta_file.tellp();
370 worker_status->
progress += progress_per_frame;
384 PackedBake *packed_data = packed_data_by_bake.
lookup_ptr(&request);
399 auto transfer_to_bake =
403 MemoryBakeFile &memory = memory_bake_files[
i];
405 const int64_t data_size = memory.data.size();
406 if (data_size == 0) {
410 std::move(memory.data));
411 const void *
data = sharing_info->data.data();
423 bake->packed = packed_bake;
435 if (!node_cache->bake.frames.is_empty()) {
454 G.is_rendering =
false;
471 &
bake.data_blocks_num,
472 &
bake.active_data_block,
474 nodes_modifier_data_block_destruct(data_block, true);
507 std::lock_guard
lock{modifier_cache.
mutex};
509 (*node_cache)->reset();
511 else if (
auto *node_cache = modifier_cache.
bake_cache_by_id.lookup_ptr(bake_id)) {
512 (*node_cache)->reset();
522 bake->packed =
nullptr;
526 *bmain,
object, nmd, bake_id);
530 const char *meta_dir = bake_path->meta_dir.c_str();
536 const char *blobs_dir = bake_path->blobs_dir.c_str();
542 if (bake_path->bake_dir.has_value()) {
543 const char *zone_bake_dir = bake_path->bake_dir->c_str();
548 *bmain,
object, nmd))
551 BLI_delete(modifier_bake_dir->c_str(),
true,
false);
620 for (
Object *
object : objects) {
639 const int id = nested_node_ref.id;
649 request.
blob_sharing = std::make_unique<bake::BlobWriteSharing>();
654 scene, *
object, *nmd,
id);
661 requests.
append(std::move(request));
701 char *
norm =
static_cast<char *
>(norm_buf.
buffer());
753 if (bake_directory_set) {
764 "Bake directory of object %s, modifier %s is empty, setting default path",
778 for (
Object *
object : objects) {
806 for (
const Object *
object : objects) {
822 absolute_bake_dir, [](
int *value) { *value = 1; }, [](
int *value) { ++(*value); });
850 bool has_path_conflict =
false;
851 bool has_existing_bake_data =
false;
852 for (
const auto &item : path_users.
items()) {
854 if (item.value > 1) {
857 "Path conflict: %d caches set to path %s",
860 has_path_conflict =
true;
865 has_existing_bake_data =
true;
869 if (has_path_conflict) {
873 if (has_existing_bake_data) {
876 IFACE_(
"Overwrite existing bake data?"),
917 for (
Object *
object : objects) {
941 if (
object ==
nullptr) {
962 if (node ==
nullptr) {
974 request.
blob_sharing = std::make_unique<bake::BlobWriteSharing>();
985 "Cannot determine bake location on disk. Falling back to packed bake.");
990 const int current_frame = scene->
r.
cfra;
999 *scene, *
object, nmd, bake_id);
1000 if (!frame_range.has_value()) {
1003 if (frame_range->is_empty()) {
1007 request.
frame_end = frame_range->last();
1011 requests.
append(std::move(request));
1050 if (
object ==
nullptr) {
1055 if (md ==
nullptr) {
1074 if (
object ==
nullptr) {
1079 if (md ==
nullptr) {
1086 *bmain, *
object, nmd, bake_id);
1129 if (
object ==
nullptr) {
1134 if (md ==
nullptr) {
1147 *bmain, op->
reports, *
object, nmd, *
bake, method);
1159 ot->name =
"Calculate Simulation to Frame";
1161 "Calculate simulations in geometry nodes modifiers from the start to current frame";
1162 ot->idname = __func__;
1172 "Calculate all selected objects instead of just the active object");
1177 ot->name =
"Bake Simulation";
1178 ot->description =
"Bake simulations in geometry nodes modifiers";
1179 ot->idname = __func__;
1186 RNA_def_boolean(
ot->srna,
"selected",
false,
"Selected",
"Bake cache on all selected objects");
1191 ot->name =
"Delete Cached Simulation";
1192 ot->description =
"Delete cached/baked simulations in geometry nodes modifiers";
1193 ot->idname = __func__;
1198 RNA_def_boolean(
ot->srna,
"selected",
false,
"Selected",
"Delete cache on all selected objects");
1210 "Name of the modifier that contains the node");
1217 ot->name =
"Bake Geometry Node";
1218 ot->description =
"Bake a single bake node or simulation";
1219 ot->idname =
"OBJECT_OT_geometry_node_bake_single";
1230 ot->name =
"Delete Geometry Node Bake";
1231 ot->description =
"Delete baked data of a single bake node or simulation";
1232 ot->idname =
"OBJECT_OT_geometry_node_bake_delete_single";
1241 ot->name =
"Pack Geometry Node Bake";
1242 ot->description =
"Pack baked data from disk into the .blend file";
1243 ot->idname =
"OBJECT_OT_geometry_node_bake_pack_single";
1252 ot->name =
"Unpack Geometry Node Bake";
1253 ot->description =
"Unpack baked data from the .blend file to disk";
1254 ot->idname =
"OBJECT_OT_geometry_node_bake_unpack_single";
1265 "Use bake from current directory (create when necessary)",
1270 "Write bake to current directory (overwrite existing bake)",
1275 "Use bake in original location (create when necessary)",
1280 "Write bake to original location (overwrite existing file)",
1282 {0,
nullptr, 0,
nullptr,
nullptr},
#define CTX_DATA_BEGIN(C, Type, instance, member)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
ModifierData * BKE_modifiers_findby_name(const Object *ob, const char *name)
#define GEO_NODE_SIMULATION_OUTPUT
PackedFile * BKE_packedfile_new_from_memory(const void *mem, int memlen, const blender::ImplicitSharingInfo *sharing_info=nullptr)
constexpr int64_t PACKED_FILE_MAX_SIZE
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
File and directory operations.
#define LISTBASE_FOREACH(type, var, list)
ATTR_WARN_UNUSED_RESULT const size_t num
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
void BLI_path_slash_native(char *path) ATTR_NONNULL(1)
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
#define BLI_path_join(...)
int BLI_path_cmp_normalized(const char *p1, const char *p2) ATTR_NONNULL(1
void BLI_path_slash_rstrip(char *path) ATTR_NONNULL(1)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
char * STRNCPY(char(&dst)[N], const char *src)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_tag_update_for_side_effect_request(Depsgraph *depsgraph, ID *id, unsigned int flags)
void DEG_time_tag_update(Main *bmain)
#define ID_BLEND_PATH(_bmain, _id)
@ NODES_MODIFIER_BAKE_TARGET_DISK
@ NODES_MODIFIER_BAKE_MODE_STILL
@ OB_FLAG_USE_SIMULATION_CACHE
bool ED_operator_object_active(bContext *C)
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void UI_popup_menu_reports(bContext *C, ReportList *reports) ATTR_NONNULL()
@ WM_JOB_TYPE_CALCULATE_SIMULATION_NODES
@ WM_JOB_TYPE_BAKE_GEOMETRY_NODES
#define NS_VIEW3D_SHADING
BMesh const char void * data
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
void append(const T &value)
const Value * lookup_ptr(const Key &key) const
Value & lookup_or_add_default(const Key &key)
Value lookup_default(const Key &key, const Value &default_value) const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
ItemIterator items() const &
Value & lookup_or_add(const Key &key, const Value &value)
constexpr bool is_empty() const
constexpr int64_t size() const
constexpr const char * data() const
constexpr const char * c_str() const
void append(const T &value)
int64_t written_size() const
const Map< std::string, OutputStream > & get_stream_by_name() const
static const char * modifier_name[LS_MODIFIER_NUM]
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
std::optional< NodesModifierBakeTarget > get_node_bake_target(const Object &object, const NodesModifierData &nmd, int node_id)
std::string get_default_modifier_bake_directory(const Main &bmain, const Object &object, const NodesModifierData &nmd)
std::optional< BakePath > get_node_bake_path(const Main &bmain, const Object &object, const NodesModifierData &nmd, int node_id)
std::optional< IndexRange > get_node_bake_frame_range(const Scene &scene, const Object &object, const NodesModifierData &nmd, int node_id)
void serialize_bake(const BakeState &bake_state, BlobWriter &blob_writer, BlobWriteSharing &blob_sharing, std::ostream &r_stream)
UnpackGeometryNodesBakeResult unpack_geometry_nodes_bake(Main &bmain, ReportList *reports, Object &object, NodesModifierData &nmd, NodesModifierBake &bake, ePF_FileStatus how)
PackGeometryNodesBakeResult pack_geometry_nodes_bake(Main &bmain, ReportList *reports, Object &object, NodesModifierData &nmd, NodesModifierBake &bake)
UnpackGeometryNodesBakeResult
std::string frame_to_file_name(const SubFrame &frame)
std::optional< std::string > get_modifier_bake_path(const Main &bmain, const Object &object, const NodesModifierData &nmd)
void clear(T **items, int *items_num, int *active_index, void(*destruct_item)(T *))
void OBJECT_OT_simulation_nodes_cache_bake(wmOperatorType *ot)
static wmOperatorStatus bake_single_node_exec(bContext *C, wmOperator *op)
static void bake_geometry_nodes_startjob(void *customdata, wmJobWorkerStatus *worker_status)
static void clear_requested_bakes_in_modifier_cache(BakeGeometryNodesJob &job)
static void bake_geometry_nodes_endjob(void *customdata)
static void simulate_to_frame_endjob(void *customdata)
static void bake_simulation_validate_paths(bContext *C, wmOperator *op, const Span< Object * > objects)
static wmOperatorStatus unpack_single_bake_invoke(bContext *C, wmOperator *op, const wmEvent *)
static wmOperatorStatus unpack_single_bake_exec(bContext *C, wmOperator *op)
static wmOperatorStatus bake_simulation_modal(bContext *C, wmOperator *, const wmEvent *)
static void simulate_to_frame_startjob(void *customdata, wmJobWorkerStatus *worker_status)
void OBJECT_OT_geometry_node_bake_delete_single(wmOperatorType *ot)
static wmOperatorStatus simulate_to_frame_invoke(bContext *C, wmOperator *op, const wmEvent *)
static wmOperatorStatus bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent *)
static wmOperatorStatus simulate_to_frame_modal(bContext *C, wmOperator *, const wmEvent *)
void OBJECT_OT_geometry_node_bake_unpack_single(wmOperatorType *ot)
static void single_bake_operator_props(wmOperatorType *ot)
void OBJECT_OT_geometry_node_bake_pack_single(wmOperatorType *ot)
static void initialize_modifier_bake_directory_if_necessary(bContext *C, Object &object, NodesModifierData &nmd, wmOperator *op)
static wmOperatorStatus delete_baked_simulation_exec(bContext *C, wmOperator *op)
static Vector< NodeBakeRequest > bake_simulation_gather_requests(bContext *C, wmOperator *op)
static wmOperatorStatus bake_single_node_modal(bContext *C, wmOperator *, const wmEvent *)
static PathUsersMap bake_simulation_get_path_users(bContext *C, const Span< Object * > objects)
static wmOperatorStatus bake_simulation_exec(bContext *C, wmOperator *op)
static bool may_have_disk_bake(const NodesModifierData &nmd)
void OBJECT_OT_geometry_node_bake_single(wmOperatorType *ot)
static wmOperatorStatus pack_single_bake_exec(bContext *C, wmOperator *op)
static bool bake_simulation_poll(bContext *C)
static bool simulate_to_frame_poll(bContext *C)
static wmOperatorStatus delete_single_bake_exec(bContext *C, wmOperator *op)
static Vector< NodeBakeRequest > collect_simulations_to_bake(Main &bmain, Scene &scene, const Span< Object * > objects)
static wmOperatorStatus bake_single_node_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void request_bakes_in_modifier_cache(BakeGeometryNodesJob &job)
void OBJECT_OT_simulation_nodes_cache_calculate_to_frame(wmOperatorType *ot)
static void reset_old_bake_cache(NodeBakeRequest &request)
static bool bake_directory_has_data(const StringRefNull absolute_bake_dir)
Map< std::string, int, default_inline_buffer_capacity(sizeof(std::string)), DefaultProbingStrategy, PathStringHash, PathStringEquality > PathUsersMap
static Vector< NodeBakeRequest > bake_single_node_gather_bake_request(bContext *C, wmOperator *op)
static wmOperatorStatus start_bake_job(bContext *C, Vector< NodeBakeRequest > requests, wmOperator *op, const BakeRequestsMode mode)
static void try_delete_bake(Main *bmain, Object &object, NodesModifierData &nmd, const int bake_id, ReportList *reports)
void OBJECT_OT_simulation_nodes_cache_delete(wmOperatorType *ot)
static void clear_data_block_references(NodesModifierBake &bake)
Object * context_active_object(const bContext *C)
uint64_t get_default_hash(const T &v, const Args &...args)
constexpr int64_t default_inline_buffer_capacity(size_t element_size)
PythonProbingStrategy<> DefaultProbingStrategy
void nodes_modifier_packed_bake_free(NodesModifierPackedBake *packed_bake)
int RNA_int_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
struct bNodeTree * node_group
NodesModifierRuntimeHandle * runtime
NodesModifierBake * bakes
NodesModifierBakeFile * meta_files
NodesModifierBakeFile * blob_files
Map< int, std::unique_ptr< SimulationNodeCache > > simulation_cache_by_id
Map< int, std::unique_ptr< BakeNodeCache > > bake_cache_by_id
NodeBakeCache * get_node_bake_cache(const int id)
Vector< std::unique_ptr< FrameCache > > frames
std::string error_message
Vector< NodeBakeRequest > bake_requests
std::optional< bake::BakePath > path
std::unique_ptr< bake::BlobWriteSharing > blob_sharing
bool operator()(const StringRef a, const StringRef b) const
uint64_t operator()(const StringRef s) const
Vector< Object * > objects
void op_enum(blender::StringRefNull opname, blender::StringRefNull propname, IDProperty *properties, blender::wm::OpCallContext context, eUI_Item_Flag flag, const int active=-1)
void operator_context_set(blender::wm::OpCallContext opcontext)
struct ReportList * reports
struct wmOperatorType * type
void WM_locked_interface_set(wmWindowManager *wm, bool lock)
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
ID * WM_operator_properties_id_lookup_from_name_or_session_uid(Main *bmain, PointerRNA *ptr, const ID_Type type)
void WM_operator_properties_id_lookup(wmOperatorType *ot, const bool add_name_prop)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)