Blender V5.0
bake_items_socket.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
7#include "BKE_node.hh"
9#include "BKE_volume_grid.hh"
10
12
13namespace blender::bke::bake {
14
16 const fn::GField &field,
17 const AttrDomain domain,
18 const StringRef attribute_name)
19{
20 if (geometry.has_pointcloud()) {
21 PointCloudComponent &component = geometry.get_component_for_write<PointCloudComponent>();
22 try_capture_field_on_geometry(component, attribute_name, domain, field);
23 }
24 if (geometry.has_mesh()) {
25 MeshComponent &component = geometry.get_component_for_write<MeshComponent>();
26 try_capture_field_on_geometry(component, attribute_name, domain, field);
27 }
28 if (geometry.has_curves()) {
29 CurveComponent &component = geometry.get_component_for_write<CurveComponent>();
30 try_capture_field_on_geometry(component, attribute_name, domain, field);
31 }
32 if (geometry.has_grease_pencil()) {
33 GreasePencilComponent &component = geometry.get_component_for_write<GreasePencilComponent>();
34 try_capture_field_on_geometry(component, attribute_name, domain, field);
35 }
36 if (geometry.has_instances()) {
37 InstancesComponent &component = geometry.get_component_for_write<InstancesComponent>();
38 try_capture_field_on_geometry(component, attribute_name, domain, field);
39 }
40}
41
42static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
43 const bNodeSocketType &stype,
44 SocketValueVariant &socket_value,
45 std::optional<StringRef> name,
46 Vector<GeometryBakeItem *> &r_geometry_bake_items)
47{
48 switch (stype.type) {
49 case SOCK_GEOMETRY: {
50 GeometrySet geometry = socket_value.extract<GeometrySet>();
51 auto item = std::make_unique<GeometryBakeItem>(std::move(geometry));
52 r_geometry_bake_items.append(item.get());
53 return item;
54 }
55 case SOCK_STRING: {
56 return std::make_unique<StringBakeItem>(socket_value.extract<std::string>());
57 }
58 case SOCK_FLOAT:
59 case SOCK_VECTOR:
60 case SOCK_INT:
61 case SOCK_BOOLEAN:
62 case SOCK_ROTATION:
63 case SOCK_MATRIX:
64 case SOCK_RGBA: {
65 if (socket_value.is_context_dependent_field()) {
66 /* Not supported here because it's not known which geometry this field belongs to. */
67 return {};
68 }
69#ifdef WITH_OPENVDB
70 if (socket_value.is_volume_grid()) {
71 bke::GVolumeGrid grid = socket_value.get<bke::GVolumeGrid>();
72 if (name) {
73 grid.get_for_write().set_name(*name);
74 }
75 return std::make_unique<VolumeGridBakeItem>(
76 std::make_unique<bke::GVolumeGrid>(std::move(grid)));
77 }
78#else
80#endif
81
82 socket_value.convert_to_single();
83 GPointer value = socket_value.get_single_ptr();
84 return std::make_unique<PrimitiveBakeItem>(*value.type(), value.get());
85 }
86 case SOCK_BUNDLE: {
87 nodes::BundlePtr bundle_ptr = socket_value.extract<nodes::BundlePtr>();
88 auto bundle_bake_item = std::make_unique<BundleBakeItem>();
89 if (bundle_ptr) {
90 const nodes::Bundle &bundle = *bundle_ptr;
91 for (const nodes::Bundle::StoredItem &bundle_item : bundle.items()) {
92 if (const auto *item_socket_value = std::get_if<nodes::BundleItemSocketValue>(
93 &bundle_item.value.value))
94 {
95 SocketValueVariant value_variant = item_socket_value->value;
96 if (std::unique_ptr<BakeItem> bake_item = move_common_socket_value_to_bake_item(
97 *item_socket_value->type, value_variant, std::nullopt, r_geometry_bake_items))
98 {
99 bundle_bake_item->items.append(
100 BundleBakeItem::Item{bundle_item.key,
101 BundleBakeItem::SocketValue{item_socket_value->type->idname,
102 std::move(bake_item)}});
103 }
104 }
105 else if (const auto *internal_value = std::get_if<nodes::BundleItemInternalValue>(
106 &bundle_item.value.value))
107 {
108 const ImplicitSharingInfo *sharing_info = internal_value->value.get();
109 if (sharing_info) {
110 sharing_info->add_user();
111 }
112 bundle_bake_item->items.append(BundleBakeItem::Item{
113 bundle_item.key,
115 }
116 }
117 }
118 return bundle_bake_item;
119 }
120 default:
121 return {};
122 }
123}
124
127 const BakeSocketConfig &config,
128 BakeDataBlockMap *data_block_map)
129{
130 BLI_assert(socket_values.size() == config.types.size());
131 BLI_assert(socket_values.size() == config.geometries_by_attribute.size());
132
133 Array<std::unique_ptr<BakeItem>> bake_items(socket_values.size());
134
135 Vector<GeometryBakeItem *> geometry_bake_items;
136
137 /* Create geometry bake items first because they are used for field evaluation. */
138 for (const int i : socket_values.index_range()) {
139 const eNodeSocketDatatype socket_type = config.types[i];
140 if (socket_type != SOCK_GEOMETRY) {
141 continue;
142 }
143 GeometrySet geometry = socket_values[i].extract<GeometrySet>();
144 auto geometry_item = std::make_unique<GeometryBakeItem>(std::move(geometry));
145 geometry_bake_items.append(geometry_item.get());
146 bake_items[i] = std::move(geometry_item);
147 }
148
149 for (const int i : socket_values.index_range()) {
150 const eNodeSocketDatatype socket_type = config.types[i];
151 const bNodeSocketType &stype = *node_socket_type_find_static(socket_type);
152 SocketValueVariant &socket_value = socket_values[i];
153 switch (socket_type) {
154 case SOCK_GEOMETRY: {
155 /* Handled already. */
156 break;
157 }
158 case SOCK_STRING: {
160 stype, socket_value, config.names[i], geometry_bake_items);
161 break;
162 }
163 case SOCK_FLOAT:
164 case SOCK_VECTOR:
165 case SOCK_INT:
166 case SOCK_BOOLEAN:
167 case SOCK_ROTATION:
168 case SOCK_MATRIX:
169 case SOCK_RGBA: {
170 if (socket_value.is_context_dependent_field()) {
171 const fn::GField &field = socket_value.get<fn::GField>();
172 const AttrDomain domain = config.domains[i];
173 const std::string attribute_name = ".bake_" + std::to_string(i);
174 const Span<int> geometry_indices = config.geometries_by_attribute[i];
175 for (const int geometry_i : geometry_indices) {
176 BLI_assert(config.types[geometry_i] == SOCK_GEOMETRY);
178 static_cast<GeometryBakeItem *>(bake_items[geometry_i].get())->geometry;
179 capture_field_on_geometry_components(geometry, field, domain, attribute_name);
180 }
181 bake_items[i] = std::make_unique<AttributeBakeItem>(attribute_name);
182 }
183 else {
185 stype, socket_value, config.names[i], geometry_bake_items);
186 }
187 break;
188 }
189 case SOCK_BUNDLE: {
191 stype, socket_value, config.names[i], geometry_bake_items);
192 break;
193 }
194 default:
195 break;
196 }
197 }
198
199 /* Cleanup geometries after fields have been evaluated. */
200 for (GeometryBakeItem *geometry_item : geometry_bake_items) {
201 GeometryBakeItem::prepare_geometry_for_bake(geometry_item->geometry, data_block_map);
202 }
203
204 for (const int i : bake_items.index_range()) {
205 if (std::unique_ptr<BakeItem> &item = bake_items[i]) {
206 item->name = config.names[i];
207 }
208 }
209
210 return bake_items;
211}
212
216[[nodiscard]] static std::optional<SocketValueVariant> copy_bake_item_to_socket_value(
217 const BakeItem &bake_item,
218 const eNodeSocketDatatype socket_type,
219 const FunctionRef<std::shared_ptr<AttributeFieldInput>(const CPPType &type)>
220 make_attribute_field,
221 BakeDataBlockMap *data_block_map,
222 Map<std::string, std::string> &r_attribute_map)
223{
224 switch (socket_type) {
225 case SOCK_GEOMETRY: {
226 if (const auto *item = dynamic_cast<const GeometryBakeItem *>(&bake_item)) {
227 bke::GeometrySet geometry = item->geometry;
229 return SocketValueVariant::From(std::move(geometry));
230 }
231 return std::nullopt;
232 }
233 case SOCK_FLOAT:
234 case SOCK_VECTOR:
235 case SOCK_INT:
236 case SOCK_BOOLEAN:
237 case SOCK_ROTATION:
238 case SOCK_MATRIX:
239 case SOCK_RGBA: {
240 const CPPType &base_type = *socket_type_to_geo_nodes_base_cpp_type(socket_type);
241 if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {
242 if (item->type() == base_type) {
243 SocketValueVariant value_variant;
244 value_variant.store_single(socket_type, item->value());
245 return value_variant;
246 }
247 return std::nullopt;
248 }
249 if (const auto *item = dynamic_cast<const AttributeBakeItem *>(&bake_item)) {
250 if (!make_attribute_field) {
251 return std::nullopt;
252 }
253 std::shared_ptr<AttributeFieldInput> attribute_field = make_attribute_field(base_type);
254 r_attribute_map.add(item->name(), attribute_field->attribute_name());
255 fn::GField field{attribute_field};
256 return SocketValueVariant::From(std::move(field));
257 }
258#ifdef WITH_OPENVDB
259 if (const auto *item = dynamic_cast<const VolumeGridBakeItem *>(&bake_item)) {
260 const GVolumeGrid &grid = *item->grid;
261 const VolumeGridType grid_type = grid->grid_type();
262 const std::optional<eNodeSocketDatatype> grid_socket_type = grid_type_to_socket_type(
263 grid_type);
264 if (!grid_socket_type) {
265 return std::nullopt;
266 }
267 if (grid_socket_type == socket_type) {
268 return bke::SocketValueVariant::From(*item->grid);
269 }
270 return std::nullopt;
271 }
272#endif
273 return std::nullopt;
274 }
275 case SOCK_STRING: {
276 if (const auto *item = dynamic_cast<const StringBakeItem *>(&bake_item)) {
277 return SocketValueVariant(std::string(item->value()));
278 }
279 return std::nullopt;
280 }
281 case SOCK_BUNDLE: {
282 if (const auto *item = dynamic_cast<const BundleBakeItem *>(&bake_item)) {
284 nodes::Bundle &bundle = const_cast<nodes::Bundle &>(*bundle_ptr);
285 for (const BundleBakeItem::Item &item : item->items) {
286 if (const auto *socket_value = std::get_if<BundleBakeItem::SocketValue>(&item.value)) {
287 const bNodeSocketType *stype = node_socket_type_find(socket_value->socket_idname);
288 if (!stype) {
289 return std::nullopt;
290 }
291 if (!stype->geometry_nodes_default_value) {
292 return std::nullopt;
293 }
294 if (std::optional<SocketValueVariant> child_value_variant =
296 *socket_value->value, stype->type, {}, data_block_map, r_attribute_map))
297 {
298 bundle.add(item.key, nodes::BundleItemSocketValue{stype, *child_value_variant});
299 }
300 else {
301 return std::nullopt;
302 }
303 }
304 if (const auto *internal_value = std::get_if<BundleBakeItem::InternalValue>(&item.value))
305 {
306 const auto *internal_data = dynamic_cast<const nodes::BundleItemInternalValueMixin *>(
307 internal_value->value.get());
308 if (!internal_data) {
309 continue;
310 }
311 internal_data->add_user();
312 bundle.add(item.key,
313 nodes::BundleItemInternalValue{ImplicitSharingPtr{internal_data}});
314 }
315 }
316 return bke::SocketValueVariant::From(std::move(bundle_ptr));
317 }
318 return std::nullopt;
319 }
320 default:
321 return std::nullopt;
322 }
323 return std::nullopt;
324}
325
326static void rename_attributes(const Span<GeometrySet *> geometries,
327 const Map<std::string, std::string> &attribute_map)
328{
329 for (GeometrySet *geometry : geometries) {
335 {
336 if (!geometry->has(type)) {
337 continue;
338 }
339 /* Avoid write access on the geometry when unnecessary to avoid copying data-blocks. */
340 const AttributeAccessor attributes_read_only = *geometry->get_component(type)->attributes();
341 if (std::none_of(attribute_map.keys().begin(),
342 attribute_map.keys().end(),
343 [&](const StringRef name) { return attributes_read_only.contains(name); }))
344 {
345 continue;
346 }
347
348 GeometryComponent &component = geometry->get_component_for_write(type);
349 MutableAttributeAccessor attributes = *component.attributes_for_write();
350 for (const MapItem<std::string, std::string> &attribute_item : attribute_map.items()) {
351 attributes.rename(attribute_item.key, attribute_item.value);
352 }
353 }
354 }
355}
356
358{
359 const bke::bNodeSocketType *typeinfo = bke::node_socket_type_find_static(socket_type);
360 return *static_cast<const SocketValueVariant *>(typeinfo->geometry_nodes_default_value);
361}
362
364 const Span<BakeItem *> bake_items,
365 const BakeSocketConfig &config,
366 BakeDataBlockMap *data_block_map,
367 FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field)
368{
369 Map<std::string, std::string> attribute_map;
370 Vector<SocketValueVariant> socket_values;
371 socket_values.reserve(bake_items.size());
372
373 for (const int i : bake_items.index_range()) {
374 const eNodeSocketDatatype socket_type = config.types[i];
375 BakeItem *bake_item = bake_items[i];
376 if (bake_item == nullptr) {
377 socket_values.append(default_initialize_socket_value(socket_type));
378 continue;
379 }
380 if (std::optional<SocketValueVariant> socket_value = copy_bake_item_to_socket_value(
381 *bake_item,
382 socket_type,
383 [&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
384 data_block_map,
385 attribute_map))
386 {
387 socket_values.append(std::move(*socket_value));
388 }
389 else {
390 socket_values.append(default_initialize_socket_value(socket_type));
391 continue;
392 }
393 if (socket_type == SOCK_GEOMETRY) {
394 auto &item = *static_cast<GeometryBakeItem *>(bake_item);
395 item.geometry.clear();
396 }
397 }
398
399 for (SocketValueVariant &socket_value : socket_values) {
400 if (socket_value.valid_for_socket(SOCK_GEOMETRY)) {
401 GeometrySet *geometry = socket_value.get_single_ptr().get<GeometrySet>();
402 rename_attributes({geometry}, attribute_map);
403 }
404 }
405
406 return socket_values;
407}
408
410 const Span<const BakeItem *> bake_items,
411 const BakeSocketConfig &config,
412 BakeDataBlockMap *data_block_map,
413 FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field)
414{
415 Map<std::string, std::string> attribute_map;
416 Vector<SocketValueVariant> socket_values;
417 socket_values.reserve(bake_items.size());
418
419 for (const int i : bake_items.index_range()) {
420 const eNodeSocketDatatype socket_type = config.types[i];
421 const BakeItem *bake_item = bake_items[i];
422 if (bake_item == nullptr) {
423 socket_values.append(default_initialize_socket_value(socket_type));
424 continue;
425 }
426
427 if (std::optional<SocketValueVariant> socket_value = copy_bake_item_to_socket_value(
428 *bake_item,
429 socket_type,
430 [&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
431 data_block_map,
432 attribute_map))
433 {
434 socket_values.append(std::move(*socket_value));
435 }
436 else {
437 socket_values.append(default_initialize_socket_value(socket_type));
438 }
439 }
440
441 for (SocketValueVariant &socket_value : socket_values) {
442 if (socket_value.valid_for_socket(SOCK_GEOMETRY)) {
443 GeometrySet *geometry = socket_value.get_single_ptr().get<GeometrySet>();
444 rename_attributes({geometry}, attribute_map);
445 }
446 }
447
448 return socket_values;
449}
450
451} // namespace blender::bke::bake
VolumeGridType
#define BLI_assert(a)
Definition BLI_assert.h:46
#define UNUSED_VARS(...)
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_BUNDLE
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_STRING
@ SOCK_RGBA
SubIterator begin() const
Definition BLI_map.hh:768
SubIterator end() const
Definition BLI_map.hh:778
int64_t size() const
IndexRange index_range() const
Definition BLI_array.hh:360
const CPPType * type() const
const void * get() const
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
KeyIterator keys() const &
Definition BLI_map.hh:875
ItemIterator items() const &
Definition BLI_map.hh:902
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void append(const T &value)
void reserve(const int64_t min_capacity)
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
bool rename(StringRef old_attribute_id, StringRef new_attribute_id)
static SocketValueVariant From(T &&value)
void store_single(eNodeSocketDatatype socket_type, const void *value)
static void prepare_geometry_for_bake(GeometrySet &geometry, BakeDataBlockMap *data_block_map)
static void try_restore_data_blocks(GeometrySet &geometry, BakeDataBlockMap *data_block_map)
Span< StoredItem > items() const
bool add(StringRef key, const BundleItemValue &value)
Array< std::unique_ptr< BakeItem > > move_socket_values_to_bake_items(MutableSpan< SocketValueVariant > socket_values, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map)
static std::optional< SocketValueVariant > copy_bake_item_to_socket_value(const BakeItem &bake_item, const eNodeSocketDatatype socket_type, const FunctionRef< std::shared_ptr< AttributeFieldInput >(const CPPType &type)> make_attribute_field, BakeDataBlockMap *data_block_map, Map< std::string, std::string > &r_attribute_map)
static std::unique_ptr< BakeItem > move_common_socket_value_to_bake_item(const bNodeSocketType &stype, SocketValueVariant &socket_value, std::optional< StringRef > name, Vector< GeometryBakeItem * > &r_geometry_bake_items)
Vector< SocketValueVariant > copy_bake_items_to_socket_values(Span< const BakeItem * > bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, FunctionRef< std::shared_ptr< AttributeFieldInput >(int, const CPPType &)> make_attribute_field)
static void rename_attributes(const Span< GeometrySet * > geometries, const Map< std::string, std::string > &attribute_map)
static SocketValueVariant default_initialize_socket_value(const eNodeSocketDatatype socket_type)
Vector< SocketValueVariant > move_bake_items_to_socket_values(Span< BakeItem * > bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, FunctionRef< std::shared_ptr< AttributeFieldInput >(int socket_index, const CPPType &)> make_attribute_field)
static void capture_field_on_geometry_components(GeometrySet &geometry, const fn::GField &field, const AttrDomain domain, const StringRef attribute_name)
std::optional< eNodeSocketDatatype > grid_type_to_socket_type(VolumeGridType type)
Definition node.cc:5314
bool try_capture_field_on_geometry(MutableAttributeAccessor attributes, const fn::FieldContext &field_context, const StringRef attribute_id, AttrDomain domain, const fn::Field< bool > &selection, const fn::GField &field)
const CPPType * socket_type_to_geo_nodes_base_cpp_type(eNodeSocketDatatype type)
Definition node.cc:5202
bNodeSocketType * node_socket_type_find(StringRef idname)
Definition node.cc:2462
bNodeSocketType * node_socket_type_find_static(int type, int subtype=0)
Definition node.cc:2471
ImplicitSharingPtr< Bundle > BundlePtr
const char * name
Defines a socket type.
Definition BKE_node.hh:158
eNodeSocketDatatype type
Definition BKE_node.hh:193
const SocketValueVariant * geometry_nodes_default_value
Definition BKE_node.hh:211
Vector< Vector< int, 1 > > geometries_by_attribute
std::variant< SocketValue, InternalValue > value
i
Definition text_draw.cc:230