78 G.is_rendering =
true;
95 for (
auto item : nmd->
runtime->cache->simulation_cache_by_id.items()) {
96 if (item.value->cache_status != bake::CacheStatus::Baked) {
101 objects_to_calc.
append(
object);
107 const float frame_step_size = 1.0f;
108 const float progress_per_frame = 1.0f /
115 if (
G.is_break || worker_status->
stop) {
124 worker_status->
progress += progress_per_frame;
139 G.is_rendering =
false;
173 "Calculate Simulation",
204 if (!use_frame_cache) {
218 std::optional<bake::BakePath>
path;
235 request.nmd->runtime->cache->requested_bakes.add(request.bake_id);
246 request.nmd->runtime->cache->requested_bakes.clear();
253 G.is_rendering =
true;
260 global_bake_start_frame = std::min(global_bake_start_frame, request.frame_start);
261 global_bake_end_frame = std::max(global_bake_end_frame, request.frame_end);
267 const int frames_to_bake = global_bake_end_frame - global_bake_start_frame + 1;
269 const float frame_step_size = 1.0f;
270 const float progress_per_frame = frame_step_size / frames_to_bake;
273 struct MemoryBakeFile {
286 for (
float frame_f = global_bake_start_frame; frame_f <= global_bake_end_frame;
287 frame_f += frame_step_size)
291 if (
G.is_break || worker_status->
stop) {
310 if (bake_cache ==
nullptr) {
313 if (bake_cache->
frames.is_empty()) {
317 if (frame_cache.
frame != frame) {
323 if (request.path.has_value()) {
327 request.path->meta_dir.c_str(),
328 (frame_file_name +
".json").c_str());
331 fstream meta_file{meta_path, std::ios::out};
333 written_size += blob_writer.written_size();
334 written_size += meta_file.tellp();
340 std::ostringstream meta_file{std::ios::binary};
343 packed_data.meta_files.append({frame_file_name +
".json", meta_file.str()});
345 blob_writer.get_stream_by_name();
346 for (
auto &&item : blob_stream_by_name.
items()) {
347 std::string data = item.value.stream->str();
351 packed_data.blob_files.append({item.key, std::move(data)});
353 written_size += blob_writer.written_size();
354 written_size += meta_file.tellp();
358 worker_status->
progress += progress_per_frame;
372 PackedBake *packed_data = packed_data_by_bake.
lookup_ptr(&request);
387 auto transfer_to_bake =
391 MemoryBakeFile &memory = memory_bake_files[i];
393 const int64_t data_size = memory.data.size();
394 if (data_size == 0) {
398 std::move(memory.data));
399 const void *data = sharing_info->data.data();
411 bake->packed = packed_bake;
416 if (request.node_type != GEO_NODE_SIMULATION_OUTPUT) {
423 if (!node_cache->bake.frames.is_empty()) {
425 node_cache->cache_status = bake::CacheStatus::Baked;
442 G.is_rendering =
false;
451 &
bake.data_blocks_num,
452 &
bake.active_data_block,
454 nodes_modifier_data_block_destruct(data_block, true);
488 std::lock_guard
lock{modifier_cache.
mutex};
490 (*node_cache)->reset();
492 else if (
auto *node_cache = modifier_cache.
bake_cache_by_id.lookup_ptr(bake_id)) {
493 (*node_cache)->reset();
503 bake->packed =
nullptr;
507 *bmain,
object, nmd, bake_id);
511 const char *meta_dir = bake_path->meta_dir.c_str();
517 const char *blobs_dir = bake_path->blobs_dir.c_str();
523 if (bake_path->bake_dir.has_value()) {
524 const char *zone_bake_dir = bake_path->bake_dir->c_str();
529 *bmain,
object, nmd))
532 BLI_delete(modifier_bake_dir->c_str(),
true,
false);
599 for (
Object *
object : objects) {
618 const int id = nested_node_ref.id;
620 if (node->type != GEO_NODE_SIMULATION_OUTPUT) {
628 request.
blob_sharing = std::make_unique<bake::BlobWriteSharing>();
633 scene, *
object, *nmd,
id);
640 requests.
append(std::move(request));
661 objects.append(
object);
679 memcpy(norm_buf.
buffer(), s.data(), s.size() + 1);
680 char *
norm =
static_cast<char *
>(norm_buf.
buffer());
732 if (bake_directory_set) {
743 "Bake directory of object %s, modifier %s is empty, setting default path",
757 for (
Object *
object : objects) {
785 for (
const Object *
object : objects) {
801 absolute_bake_dir, [](
int *value) { *value = 1; }, [](
int *value) { ++(*value); });
819 objects.append(
object);
827 bool has_path_conflict =
false;
828 bool has_existing_bake_data =
false;
829 for (
const auto &item : path_users.
items()) {
831 if (item.value > 1) {
834 "Path conflict: %d caches set to path %s",
837 has_path_conflict =
true;
842 has_existing_bake_data =
true;
846 if (has_path_conflict) {
850 if (has_existing_bake_data) {
853 IFACE_(
"Overwrite existing bake data?"),
882 objects.append(
object);
886 if (objects.is_empty()) {
890 for (
Object *
object : objects) {
914 if (
object ==
nullptr) {
940 if (node ==
nullptr) {
943 if (!
ELEM(node->type, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_BAKE)) {
952 request.
blob_sharing = std::make_unique<bake::BlobWriteSharing>();
963 "Can't determine bake location on disk. Falling back to packed bake.");
968 const int current_frame = scene->r.cfra;
977 *scene, *
object, nmd, bake_id);
978 if (!frame_range.has_value()) {
981 if (frame_range->is_empty()) {
989 requests.
append(std::move(request));
1024 if (
object ==
nullptr) {
1034 if (md ==
nullptr) {
1053 if (
object ==
nullptr) {
1063 if (md ==
nullptr) {
1070 *bmain, *
object, nmd, bake_id);
1112 if (
object ==
nullptr) {
1122 if (md ==
nullptr) {
1135 *bmain, op->
reports, *
object, nmd, *
bake, method);
1136 if (result != bake::UnpackGeometryNodesBakeResult::Success) {
1147 ot->
name =
"Calculate Simulation to Frame";
1149 "Calculate simulations in geometry nodes modifiers from the start to current frame";
1160 "Calculate all selected objects instead of just the active object");
1165 ot->
name =
"Bake Simulation";
1166 ot->
description =
"Bake simulations in geometry nodes modifiers";
1179 ot->
name =
"Delete Cached Simulation";
1180 ot->
description =
"Delete cached/baked simulations in geometry nodes modifiers";
1198 "Name of the modifier that contains the node");
1205 ot->
name =
"Bake Geometry Node";
1207 ot->
idname =
"OBJECT_OT_geometry_node_bake_single";
1218 ot->
name =
"Delete Geometry Node Bake";
1219 ot->
description =
"Delete baked data of a single bake node or simulation";
1220 ot->
idname =
"OBJECT_OT_geometry_node_bake_delete_single";
1229 ot->
name =
"Pack Geometry Node Bake";
1230 ot->
description =
"Pack baked data from disk into the .blend file";
1231 ot->
idname =
"OBJECT_OT_geometry_node_bake_pack_single";
1240 ot->
name =
"Unpack Geometry Node Bake";
1241 ot->
description =
"Unpack baked data from the .blend file to disk";
1242 ot->
idname =
"OBJECT_OT_geometry_node_bake_unpack_single";
1253 "Use bake from current directory (create when necessary)",
1258 "Write bake to current directory (overwrite existing bake)",
1263 "Use bake in original location (create when necessary)",
1268 "Write bake to original location (overwrite existing file)",
1270 {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)
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)
#define BLI_SCOPED_DEFER(function_to_defer)
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
#define STRNCPY(dst, src)
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
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 uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, const int active=-1)
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()
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
@ WM_JOB_TYPE_CALCULATE_SIMULATION_NODES
@ WM_JOB_TYPE_BAKE_GEOMETRY_NODES
#define NS_VIEW3D_SHADING
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
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
ItemIterator items() const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Value & lookup_or_add(const Key &key, const Value &value)
constexpr bool is_empty() const
constexpr const char * c_str() const
void append(const T &value)
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static const char * modifier_name[LS_MODIFIER_NUM]
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 *))
static int delete_single_bake_exec(bContext *C, wmOperator *op)
void OBJECT_OT_simulation_nodes_cache_bake(wmOperatorType *ot)
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 int bake_simulation_modal(bContext *C, wmOperator *, const wmEvent *)
static void bake_simulation_validate_paths(bContext *C, wmOperator *op, const Span< Object * > objects)
static void try_delete_bake(bContext *C, Object &object, NodesModifierData &nmd, const int bake_id, ReportList *reports)
static int unpack_single_bake_exec(bContext *C, wmOperator *op)
static int bake_single_node_exec(bContext *C, wmOperator *op)
static void simulate_to_frame_startjob(void *customdata, wmJobWorkerStatus *worker_status)
static int bake_simulation_exec(bContext *C, wmOperator *op)
void OBJECT_OT_geometry_node_bake_delete_single(wmOperatorType *ot)
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 int bake_single_node_modal(bContext *C, wmOperator *, const wmEvent *)
static Vector< NodeBakeRequest > bake_simulation_gather_requests(bContext *C, wmOperator *op)
static int unpack_single_bake_invoke(bContext *C, wmOperator *op, const wmEvent *)
static PathUsersMap bake_simulation_get_path_users(bContext *C, const Span< Object * > objects)
static bool may_have_disk_bake(const NodesModifierData &nmd)
void OBJECT_OT_geometry_node_bake_single(wmOperatorType *ot)
static int start_bake_job(bContext *C, Vector< NodeBakeRequest > requests, wmOperator *op, const BakeRequestsMode mode)
static int delete_baked_simulation_exec(bContext *C, wmOperator *op)
static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int simulate_to_frame_modal(bContext *C, wmOperator *, const wmEvent *)
static bool bake_simulation_poll(bContext *C)
static bool simulate_to_frame_poll(bContext *C)
static Vector< NodeBakeRequest > collect_simulations_to_bake(Main &bmain, Scene &scene, const Span< Object * > objects)
static int simulate_to_frame_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)
static Vector< NodeBakeRequest > bake_single_node_gather_bake_request(bContext *C, wmOperator *op)
static int bake_single_node_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int pack_single_bake_exec(bContext *C, wmOperator *op)
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)
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)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
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)
unsigned __int64 uint64_t
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
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
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
struct ReportList * reports
struct wmOperatorType * type
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_set_locked_interface(wmWindowManager *wm, bool lock)
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)
int WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)