Blender V4.3
bake_geometry_nodes_modifier.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <sstream>
6
8#include "BKE_collection.hh"
9#include "BKE_main.hh"
10
11#include "DNA_modifier_types.h"
12#include "DNA_node_types.h"
13
14#include "BLI_binary_search.hh"
15#include "BLI_fileops.hh"
16#include "BLI_path_utils.hh"
17#include "BLI_string.h"
18
19#include "MOD_nodes.hh"
20
21namespace blender::bke::bake {
22
24{
25 std::destroy_at(this);
26 new (this) SimulationNodeCache();
27}
28
30{
31 std::destroy_at(this);
32 new (this) BakeNodeCache();
33}
34
36{
37 std::destroy_at(this);
38 new (this) NodeBakeCache();
39}
40
42{
43 if (this->frames.is_empty()) {
44 return {};
45 }
46 const int start_frame = this->frames.first()->frame.frame();
47 const int end_frame = this->frames.last()->frame.frame();
48 return IndexRange::from_begin_end_inclusive(start_frame, end_frame);
49}
50
52{
53 std::unique_ptr<SimulationNodeCache> *ptr = this->simulation_cache_by_id.lookup_ptr(id);
54 return ptr ? (*ptr).get() : nullptr;
55}
56
58{
59 std::unique_ptr<BakeNodeCache> *ptr = this->bake_cache_by_id.lookup_ptr(id);
60 return ptr ? (*ptr).get() : nullptr;
61}
62
64{
65 if (SimulationNodeCache *cache = this->get_simulation_node_cache(id)) {
66 return &cache->bake;
67 }
68 if (BakeNodeCache *cache = this->get_bake_node_cache(id)) {
69 return &cache->bake;
70 }
71 return nullptr;
72}
73
75{
76 if (SimulationNodeCache *cache = this->get_simulation_node_cache(id)) {
77 cache->reset();
78 }
79 if (BakeNodeCache *cache = this->get_bake_node_cache(id)) {
80 cache->reset();
81 }
82}
83
85{
86 FOREACH_SCENE_OBJECT_BEGIN (&scene, ob) {
87 LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
88 if (md->type != eModifierType_Nodes) {
89 continue;
90 }
91 NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
92 if (!nmd->runtime->cache) {
93 continue;
94 }
95 for (auto item : nmd->runtime->cache->simulation_cache_by_id.items()) {
96 item.value->reset();
97 }
98 }
99 }
101}
102
103std::optional<std::string> get_modifier_bake_path(const Main &bmain,
104 const Object &object,
105 const NodesModifierData &nmd)
106{
107 if (StringRef(nmd.bake_directory).is_empty()) {
108 return std::nullopt;
109 }
111 return nmd.bake_directory;
112 }
113 const char *base_path = ID_BLEND_PATH(&bmain, &object.id);
114 if (StringRef(base_path).is_empty()) {
115 return std::nullopt;
116 }
117 char absolute_bake_dir[FILE_MAX];
118 STRNCPY(absolute_bake_dir, nmd.bake_directory);
119 BLI_path_abs(absolute_bake_dir, base_path);
120 return absolute_bake_dir;
121}
122
123std::optional<NodesModifierBakeTarget> get_node_bake_target(const Object & /*object*/,
124 const NodesModifierData &nmd,
125 int node_id)
126{
127 const NodesModifierBake *bake = nmd.find_bake(node_id);
128 if (!bake) {
129 return std::nullopt;
130 }
131 if (bake->bake_target != NODES_MODIFIER_BAKE_TARGET_INHERIT) {
132 return NodesModifierBakeTarget(bake->bake_target);
133 }
136 }
138}
139
140std::optional<bake::BakePath> get_node_bake_path(const Main &bmain,
141 const Object &object,
142 const NodesModifierData &nmd,
143 int node_id)
144{
145 const NodesModifierBake *bake = nmd.find_bake(node_id);
146 if (bake == nullptr) {
147 return std::nullopt;
148 }
150 if (StringRef(bake->directory).is_empty()) {
151 return std::nullopt;
152 }
153 if (!BLI_path_is_rel(bake->directory)) {
154 return BakePath::from_single_root(bake->directory);
155 }
156 const char *base_path = ID_BLEND_PATH(&bmain, &object.id);
157 if (StringRef(base_path).is_empty()) {
158 return std::nullopt;
159 }
160 char absolute_bake_dir[FILE_MAX];
161 STRNCPY(absolute_bake_dir, bake->directory);
162 BLI_path_abs(absolute_bake_dir, base_path);
163 return bake::BakePath::from_single_root(absolute_bake_dir);
164 }
165 const std::optional<std::string> modifier_bake_path = get_modifier_bake_path(bmain, object, nmd);
166 if (!modifier_bake_path) {
167 return std::nullopt;
168 }
169 char bake_dir[FILE_MAX];
171 bake_dir, sizeof(bake_dir), modifier_bake_path->c_str(), std::to_string(node_id).c_str());
172 return bake::BakePath::from_single_root(bake_dir);
173}
174
175static IndexRange fix_frame_range(const int start, const int end)
176{
177 const int num_frames = std::max(1, end - start + 1);
178 return IndexRange(start, num_frames);
179}
180
181std::optional<IndexRange> get_node_bake_frame_range(const Scene &scene,
182 const Object & /*object*/,
183 const NodesModifierData &nmd,
184 int node_id)
185{
186 const NodesModifierBake *bake = nmd.find_bake(node_id);
187 if (bake == nullptr) {
188 return std::nullopt;
189 }
191 return fix_frame_range(bake->frame_start, bake->frame_end);
192 }
193 if (scene.flag & SCE_CUSTOM_SIMULATION_RANGE) {
194 return fix_frame_range(scene.simulation_frame_start, scene.simulation_frame_end);
195 }
196 return fix_frame_range(scene.r.sfra, scene.r.efra);
197}
198
203static std::string escape_name(const StringRef name)
204{
205 std::stringstream ss;
206 for (const char c : name) {
207 /* Only some letters allowed. Digits are not because they could lead to name collisions. */
208 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
209 ss << c;
210 }
211 else {
212 ss << int(c);
213 }
214 }
215 return ss.str();
216}
217
218static std::string get_blend_file_name(const Main &bmain)
219{
220 const StringRefNull blend_file_path = BKE_main_blendfile_path(&bmain);
221 char blend_name[FILE_MAX];
222
223 BLI_path_split_file_part(blend_file_path.c_str(), blend_name, sizeof(blend_name));
224 const int64_t type_start_index = StringRef(blend_name).rfind(".");
225 if (type_start_index == StringRef::not_found) {
226 return "";
227 }
228 blend_name[type_start_index] = '\0';
229 return "blendcache_" + StringRef(blend_name);
230}
231
232static std::string get_modifier_directory_name(const Object &object, const ModifierData &md)
233{
234 const std::string object_name_escaped = escape_name(object.id.name + 2);
235 const std::string modifier_name_escaped = escape_name(md.name);
236 return object_name_escaped + "_" + modifier_name_escaped;
237}
238
240 const Object &object,
241 const NodesModifierData &nmd)
242{
243 char dir[FILE_MAX];
244 /* Make path that's relative to the .blend file. */
245 BLI_path_join(dir,
246 sizeof(dir),
247 "//",
248 get_blend_file_name(bmain).c_str(),
249 get_modifier_directory_name(object, nmd.modifier).c_str());
250 return dir;
251}
252
253std::string get_default_node_bake_directory(const Main &bmain,
254 const Object &object,
255 const NodesModifierData &nmd,
256 int node_id)
257{
258 char dir[FILE_MAX];
259 BLI_path_join(dir,
260 sizeof(dir),
261 "//",
262 get_blend_file_name(bmain).c_str(),
263 get_modifier_directory_name(object, nmd.modifier).c_str(),
264 std::to_string(node_id).c_str());
265 return dir;
266}
267
268} // namespace blender::bke::bake
#define FOREACH_SCENE_OBJECT_END
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
File and directory operations.
#define LISTBASE_FOREACH(type, var, list)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
NodesModifierBakeTarget
@ NODES_MODIFIER_BAKE_TARGET_PACKED
@ NODES_MODIFIER_BAKE_TARGET_INHERIT
@ NODES_MODIFIER_BAKE_CUSTOM_PATH
@ NODES_MODIFIER_BAKE_CUSTOM_SIMULATION_FRAME_RANGE
@ eModifierType_Nodes
@ SCE_CUSTOM_SIMULATION_RANGE
constexpr int64_t first() const
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
static constexpr int64_t not_found
constexpr int64_t rfind(char c, int64_t pos=INT64_MAX) const
constexpr bool is_empty() const
constexpr const char * c_str() const
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
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)
static IndexRange fix_frame_range(const int start, const int end)
std::optional< IndexRange > get_node_bake_frame_range(const Scene &scene, const Object &object, const NodesModifierData &nmd, int node_id)
static std::string escape_name(const StringRef name)
void scene_simulation_states_reset(Scene &scene)
static std::string get_blend_file_name(const Main &bmain)
std::optional< std::string > get_modifier_bake_path(const Main &bmain, const Object &object, const NodesModifierData &nmd)
static std::string get_modifier_directory_name(const Object &object, const ModifierData &md)
std::string get_default_node_bake_directory(const Main &bmain, const Object &object, const NodesModifierData &nmd, int node_id)
__int64 int64_t
Definition stdint.h:89
NodesModifierRuntimeHandle * runtime
static BakePath from_single_root(StringRefNull root_dir)
BakeNodeCache * get_bake_node_cache(const int id)
Map< int, std::unique_ptr< SimulationNodeCache > > simulation_cache_by_id
Map< int, std::unique_ptr< BakeNodeCache > > bake_cache_by_id
SimulationNodeCache * get_simulation_node_cache(const int id)
NodeBakeCache * get_node_bake_cache(const int id)
PointerRNA * ptr
Definition wm_files.cc:4126