75 G.is_rendering =
true;
92 for (
auto item : nmd->
runtime->cache->simulation_cache_by_id.items()) {
98 objects_to_calc.
append(
object);
101 worker_status->progress = 0.0f;
102 worker_status->do_update =
true;
104 const float frame_step_size = 1.0f;
105 const float progress_per_frame = 1.0f /
112 if (
G.is_break || worker_status->stop) {
121 worker_status->progress += progress_per_frame;
122 worker_status->do_update =
true;
128 worker_status->progress = 1.0f;
129 worker_status->do_update =
true;
136 G.is_rendering =
false;
172 "Calculate Simulation",
205 if (!use_frame_cache) {
219 std::optional<bake::BakePath>
path;
247 request.
nmd->
runtime->cache->requested_bakes.clear();
254 G.is_rendering =
true;
261 global_bake_start_frame = std::min(global_bake_start_frame, request.
frame_start);
262 global_bake_end_frame = std::max(global_bake_end_frame, request.
frame_end);
265 worker_status->progress = 0.0f;
266 worker_status->do_update =
true;
268 const int frames_to_bake = global_bake_end_frame - global_bake_start_frame + 1;
270 const float frame_step_size = 1.0f;
271 const float progress_per_frame = frame_step_size / frames_to_bake;
274 struct MemoryBakeFile {
287 for (
float frame_f = global_bake_start_frame; frame_f <= global_bake_end_frame;
288 frame_f += frame_step_size)
292 if (
G.is_break || worker_status->stop) {
311 if (bake_cache ==
nullptr) {
314 if (bake_cache->
frames.is_empty()) {
318 if (frame_cache.
frame != frame) {
324 if (request.
path.has_value()) {
328 request.
path->meta_dir.c_str(),
329 (frame_file_name +
".json").c_str());
332 fstream meta_file{meta_path, std::ios::out};
335 written_size += meta_file.tellp();
341 std::ostringstream meta_file{std::ios::binary};
344 packed_data.meta_files.append({frame_file_name +
".json", meta_file.str()});
347 for (
auto &&item : blob_stream_by_name.
items()) {
348 std::string
data = item.value.stream->str();
352 packed_data.blob_files.append({item.key, std::move(
data)});
355 written_size += meta_file.tellp();
359 worker_status->progress += progress_per_frame;
360 worker_status->do_update =
true;
373 PackedBake *packed_data = packed_data_by_bake.
lookup_ptr(&request);
388 auto transfer_to_bake =
392 MemoryBakeFile &memory = memory_bake_files[
i];
394 const int64_t data_size = memory.data.size();
395 if (data_size == 0) {
399 std::move(memory.data));
400 const void *
data = sharing_info->data.data();
412 bake->packed = packed_bake;
424 if (!node_cache->bake.frames.is_empty()) {
435 worker_status->progress = 1.0f;
436 worker_status->do_update =
true;
443 G.is_rendering =
false;
452 &
bake.data_blocks_num,
453 &
bake.active_data_block,
455 nodes_modifier_data_block_destruct(data_block, true);
489 std::lock_guard
lock{modifier_cache.
mutex};
491 (*node_cache)->reset();
493 else if (
auto *node_cache = modifier_cache.
bake_cache_by_id.lookup_ptr(bake_id)) {
494 (*node_cache)->reset();
504 bake->packed =
nullptr;
508 *bmain,
object, nmd, bake_id);
512 const char *meta_dir = bake_path->meta_dir.c_str();
518 const char *blobs_dir = bake_path->blobs_dir.c_str();
524 if (bake_path->bake_dir.has_value()) {
525 const char *zone_bake_dir = bake_path->bake_dir->c_str();
530 *bmain,
object, nmd))
533 BLI_delete(modifier_bake_dir->c_str(),
true,
false);
570 wmJobWorkerStatus worker_status{};
600 for (
Object *
object : objects) {
619 const int id = nested_node_ref.id;
629 request.
blob_sharing = std::make_unique<bake::BlobWriteSharing>();
634 scene, *
object, *nmd,
id);
641 requests.
append(std::move(request));
681 char *
norm =
static_cast<char *
>(norm_buf.
buffer());
733 if (bake_directory_set) {
744 "Bake directory of object %s, modifier %s is empty, setting default path",
758 for (
Object *
object : objects) {
786 for (
const Object *
object : objects) {
802 absolute_bake_dir, [](
int *value) { *value = 1; }, [](
int *value) { ++(*value); });
830 bool has_path_conflict =
false;
831 bool has_existing_bake_data =
false;
832 for (
const auto &item : path_users.
items()) {
834 if (item.value > 1) {
837 "Path conflict: %d caches set to path %s",
840 has_path_conflict =
true;
845 has_existing_bake_data =
true;
849 if (has_path_conflict) {
853 if (has_existing_bake_data) {
856 IFACE_(
"Overwrite existing bake data?"),
895 for (
Object *
object : objects) {
919 if (
object ==
nullptr) {
945 if (node ==
nullptr) {
957 request.
blob_sharing = std::make_unique<bake::BlobWriteSharing>();
968 "Can't determine bake location on disk. Falling back to packed bake.");
973 const int current_frame = scene->
r.
cfra;
982 *scene, *
object, nmd, bake_id);
983 if (!frame_range.has_value()) {
986 if (frame_range->is_empty()) {
994 requests.
append(std::move(request));
1033 if (
object ==
nullptr) {
1043 if (md ==
nullptr) {
1062 if (
object ==
nullptr) {
1072 if (md ==
nullptr) {
1079 *bmain, *
object, nmd, bake_id);
1123 if (
object ==
nullptr) {
1133 if (md ==
nullptr) {
1146 *bmain, op->
reports, *
object, nmd, *
bake, method);
1158 ot->name =
"Calculate Simulation to Frame";
1160 "Calculate simulations in geometry nodes modifiers from the start to current frame";
1161 ot->idname = __func__;
1171 "Calculate all selected objects instead of just the active object");
1176 ot->name =
"Bake Simulation";
1177 ot->description =
"Bake simulations in geometry nodes modifiers";
1178 ot->idname = __func__;
1185 RNA_def_boolean(
ot->srna,
"selected",
false,
"Selected",
"Bake cache on all selected objects");
1190 ot->name =
"Delete Cached Simulation";
1191 ot->description =
"Delete cached/baked simulations in geometry nodes modifiers";
1192 ot->idname = __func__;
1197 RNA_def_boolean(
ot->srna,
"selected",
false,
"Selected",
"Delete cache on all selected objects");
1209 "Name of the modifier that contains the node");
1216 ot->name =
"Bake Geometry Node";
1217 ot->description =
"Bake a single bake node or simulation";
1218 ot->idname =
"OBJECT_OT_geometry_node_bake_single";
1229 ot->name =
"Delete Geometry Node Bake";
1230 ot->description =
"Delete baked data of a single bake node or simulation";
1231 ot->idname =
"OBJECT_OT_geometry_node_bake_delete_single";
1240 ot->name =
"Pack Geometry Node Bake";
1241 ot->description =
"Pack baked data from disk into the .blend file";
1242 ot->idname =
"OBJECT_OT_geometry_node_bake_pack_single";
1251 ot->name =
"Unpack Geometry Node Bake";
1252 ot->description =
"Unpack baked data from the .blend file to disk";
1253 ot->idname =
"OBJECT_OT_geometry_node_bake_unpack_single";
1264 "Use bake from current directory (create when necessary)",
1269 "Write bake to current directory (overwrite existing bake)",
1274 "Use bake in original location (create when necessary)",
1279 "Write bake to original location (overwrite existing file)",
1281 {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)
ATTR_WARN_UNUSED_RESULT const size_t num
#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
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)
@ 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()
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
void uiItemsFullEnumO(uiLayout *layout, blender::StringRefNull opname, blender::StringRefNull propname, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, const int active=-1)
@ 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
#define ID_BLEND_PATH(_bmain, _id)
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 void try_delete_bake(bContext *C, Object &object, NodesModifierData &nmd, const int bake_id, ReportList *reports)
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)
Map< std::string, int, default_inline_buffer_capacity(sizeof(std::string)), DefaultProbingStrategy, PathStringHash, PathStringEquality > PathUsersMap
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)
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)
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)
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)
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
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)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)