Blender V5.0
shader_nodes_inline.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <fmt/format.h>
6#include <variant>
7
9#include "BKE_lib_id.hh"
12
13#include "BLI_listbase.h"
14#include "BLI_math_vector.h"
15#include "BLI_stack.hh"
16
17#include "NOD_menu_value.hh"
18#include "NOD_multi_function.hh"
22
23namespace blender::nodes {
24namespace {
25
26struct BundleSocketValue;
27using BundleSocketValuePtr = std::shared_ptr<BundleSocketValue>;
28
29struct FallbackValue {};
30
32struct DanglingValue {};
33
34struct NodeAndSocket {
35 bNode *node = nullptr;
36 bNodeSocket *socket = nullptr;
37};
38
39struct PrimitiveSocketValue {
40 std::variant<int, float, bool, ColorGeometry4f, float3, MenuValue> value;
41
42 const void *buffer() const
43 {
44 return std::visit([](auto &&value) -> const void * { return &value; }, value);
45 }
46
47 void *buffer()
48 {
49 return const_cast<void *>(const_cast<const PrimitiveSocketValue *>(this)->buffer());
50 }
51
52 static PrimitiveSocketValue from_value(const GPointer value)
53 {
54 const CPPType &type = *value.type();
55 if (type.is<int>()) {
56 return {*static_cast<const int *>(value.get())};
57 }
58 if (type.is<float>()) {
59 return {*static_cast<const float *>(value.get())};
60 }
61 if (type.is<bool>()) {
62 return {*static_cast<const bool *>(value.get())};
63 }
64 if (type.is<ColorGeometry4f>()) {
65 return {*static_cast<const ColorGeometry4f *>(value.get())};
66 }
67 if (type.is<float3>()) {
68 return {*static_cast<const float3 *>(value.get())};
69 }
70 if (type.is<MenuValue>()) {
71 return {*static_cast<const MenuValue *>(value.get())};
72 }
74 return {};
75 }
76};
77
79struct LinkedSocketValue {
80 bNode *node = nullptr;
81 bNodeSocket *socket = nullptr;
82};
83
85struct InputSocketValue {
86 const bNodeSocket *socket = nullptr;
87};
88
89struct ClosureZoneValue {
90 const bke::bNodeTreeZone *zone = nullptr;
91 const ComputeContext *closure_creation_context = nullptr;
92};
93
94struct SocketValue {
100 std::variant<FallbackValue,
101 DanglingValue,
102 LinkedSocketValue,
103 InputSocketValue,
104 PrimitiveSocketValue,
105 ClosureZoneValue,
106 BundleSocketValuePtr>
107 value;
108
110 std::optional<PrimitiveSocketValue> to_primitive(const bke::bNodeSocketType &type) const
111 {
112 if (const auto *primitive_value = std::get_if<PrimitiveSocketValue>(&this->value)) {
113 return *primitive_value;
114 }
115 if (const auto *input_socket_value = std::get_if<InputSocketValue>(&this->value)) {
116 const bNodeSocket &socket = *input_socket_value->socket;
117 BLI_assert(socket.type == type.type);
118 if (!socket.runtime->declaration) {
119 return std::nullopt;
120 }
121 if (socket.runtime->declaration->default_input_type != NODE_DEFAULT_INPUT_VALUE) {
122 return std::nullopt;
123 }
124 switch (socket.typeinfo->type) {
125 case SOCK_FLOAT:
126 return PrimitiveSocketValue{socket.default_value_typed<bNodeSocketValueFloat>()->value};
127 case SOCK_INT:
128 return PrimitiveSocketValue{socket.default_value_typed<bNodeSocketValueInt>()->value};
129 case SOCK_BOOLEAN:
130 return PrimitiveSocketValue{
131 socket.default_value_typed<bNodeSocketValueBoolean>()->value};
132 case SOCK_VECTOR:
133 return PrimitiveSocketValue{
134 float3(socket.default_value_typed<bNodeSocketValueVector>()->value)};
135 case SOCK_RGBA:
136 return PrimitiveSocketValue{
137 ColorGeometry4f(socket.default_value_typed<bNodeSocketValueRGBA>()->value)};
138 case SOCK_MENU:
139 return PrimitiveSocketValue{
140 MenuValue(socket.default_value_typed<bNodeSocketValueMenu>()->value)};
141 default:
142 return std::nullopt;
143 }
144 }
145 if (std::get_if<FallbackValue>(&this->value)) {
146 switch (type.type) {
147 case SOCK_INT:
148 case SOCK_BOOLEAN:
149 case SOCK_VECTOR:
150 case SOCK_RGBA:
151 case SOCK_FLOAT:
152 return PrimitiveSocketValue::from_value(
153 {type.base_cpp_type, type.base_cpp_type->default_value()});
154 default:
155 return std::nullopt;
156 }
157 }
158 return std::nullopt;
159 }
160};
161
162struct BundleSocketValue {
163 struct Item {
164 std::string key;
165 SocketValue value;
166 const bke::bNodeSocketType *socket_type = nullptr;
167 };
168
169 Vector<Item> items;
170};
171
172struct PreservedZone {
173 bNode *input_node = nullptr;
174 bNode *output_node = nullptr;
175};
176
177class ShaderNodesInliner {
178 private:
180 ResourceScope scope_;
182 const bNodeTree &src_tree_;
184 bNodeTree &dst_tree_;
186 InlineShaderNodeTreeParams &params_;
188 bke::ComputeContextCache compute_context_cache_;
193 Map<const ComputeContext *, const ComputeContext *> parent_zone_contexts_;
195 Map<SocketInContext, SocketValue> value_by_socket_;
200 Map<NodeInContext, PreservedZone> copied_zone_by_zone_output_node_;
202 Stack<SocketInContext> scheduled_sockets_stack_;
204 const bke::DataTypeConversions &data_type_conversions_;
206 int dst_node_counter_ = 0;
207
208 public:
209 ShaderNodesInliner(const bNodeTree &src_tree,
210 bNodeTree &dst_tree,
211 InlineShaderNodeTreeParams &params)
212 : src_tree_(src_tree),
213 dst_tree_(dst_tree),
214 params_(params),
215 data_type_conversions_(bke::get_implicit_type_conversions())
216 {
217 }
218
219 bool do_inline()
220 {
221 src_tree_.ensure_topology_cache();
222 if (src_tree_.has_available_link_cycle()) {
223 return false;
224 }
225
226 const Vector<SocketInContext> final_output_sockets = this->find_final_output_sockets();
227
228 /* Evaluation starts at the final output sockets which will request the evaluation of whether
229 * sockets are linked to them. */
230 for (const SocketInContext &socket : final_output_sockets) {
231 this->schedule_socket(socket);
232 }
233
234 /* Evaluate until all scheduled sockets have a value. While evaluating a single socket, it may
235 * either end up having a value, or request more other sockets that need to be evaluated first.
236 *
237 * This uses an explicit stack instead of recursion to avoid stack overflows which can easily
238 * happen when there are long chains of nodes (or e.g. repeat zones with many iterations). */
239 while (!scheduled_sockets_stack_.is_empty()) {
240 const SocketInContext socket = scheduled_sockets_stack_.peek();
241 const int old_stack_size = scheduled_sockets_stack_.size();
242
243 this->handle_socket(socket);
244
245 if (scheduled_sockets_stack_.size() == old_stack_size) {
246 /* No additional dependencies were pushed, so this socket is fully handled and can be
247 * popped from the stack. */
248 BLI_assert(socket == scheduled_sockets_stack_.peek());
249 scheduled_sockets_stack_.pop();
250 }
251 }
252
253 /* Create actual output nodes. */
254 Map<NodeInContext, bNode *> final_output_nodes;
255 for (const SocketInContext &socket : final_output_sockets) {
256 const NodeInContext src_node = socket.owner_node();
257 bNode *copied_node = final_output_nodes.lookup_or_add_cb(src_node, [&]() {
258 Map<const bNodeSocket *, bNodeSocket *> socket_map;
259 bNode *copied_node = bke::node_copy_with_mapping(&dst_tree_,
260 *src_node.node,
261 this->node_copy_flag(),
262 std::nullopt,
263 this->get_next_node_identifier(),
264 socket_map);
265 copied_node->parent = nullptr;
266 return copied_node;
267 });
268 bNodeSocket *copied_socket = static_cast<bNodeSocket *>(
269 BLI_findlink(&copied_node->inputs, socket.socket->index()));
270 this->set_input_socket_value(
271 *src_node, *copied_node, *copied_socket, value_by_socket_.lookup(socket));
272 }
273
274 this->restore_zones_in_output_tree();
275 this->position_nodes_in_output_tree();
276 return true;
277 }
278
279 Vector<SocketInContext> find_final_output_sockets()
280 {
281 Vector<TreeInContext> trees;
282 this->find_trees_potentially_containing_shader_outputs_recursive(nullptr, src_tree_, trees);
283
284 Vector<SocketInContext> output_sockets;
285 auto add_output_type = [&](const char *output_type) {
286 for (const TreeInContext &tree : trees) {
287 const bke::bNodeTreeZones &zones = *tree->zones();
288 for (const bNode *node : tree->nodes_by_type(output_type)) {
289 const bke::bNodeTreeZone *zone = zones.get_zone_by_node(node->identifier);
290 if (zone) {
291 params_.r_error_messages.append({node, TIP_("Output node must not be in zone")});
292 continue;
293 }
294 for (const bNodeSocket *socket : node->input_sockets()) {
295 output_sockets.append({tree.context, socket});
296 }
297 }
298 }
299 };
300
301 /* owner_id can be null for DefaultSurfaceNodeTree. */
302 ID_Type tree_type = src_tree_.owner_id ? GS(src_tree_.owner_id->name) : ID_MA;
303
304 switch (tree_type) {
305 case ID_MA:
306 add_output_type("ShaderNodeOutputMaterial");
307 add_output_type("ShaderNodeOutputAOV");
308 add_output_type("ShaderNodeOutputLight");
309 break;
310 case ID_WO:
311 add_output_type("ShaderNodeOutputWorld");
312 add_output_type("ShaderNodeOutputAOV");
313 break;
314 case ID_LA:
315 add_output_type("ShaderNodeOutputLight");
316 break;
317 default:
319 }
320
321 return output_sockets;
322 }
323
324 void find_trees_potentially_containing_shader_outputs_recursive(const ComputeContext *context,
325 const bNodeTree &tree,
326 Vector<TreeInContext> &r_trees)
327 {
328 const bke::bNodeTreeZones *zones = src_tree_.zones();
329 if (!zones) {
330 return;
331 }
332 if (tree.has_available_link_cycle()) {
333 return;
334 }
335 r_trees.append({context, &tree});
336 for (const bNode *group_node : tree.group_nodes()) {
337 if (group_node->is_muted()) {
338 continue;
339 }
340 const bNodeTree *group = id_cast<const bNodeTree *>(group_node->id);
341 if (!group || ID_MISSING(&group->id)) {
342 continue;
343 }
344 group->ensure_topology_cache();
345 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(group_node->identifier);
346 if (zone) {
347 /* Node groups in zones are ignored. */
348 continue;
349 }
350 const ComputeContext &group_context = compute_context_cache_.for_group_node(
351 context, group_node->identifier, &tree);
352 this->find_trees_potentially_containing_shader_outputs_recursive(
353 &group_context, *group, r_trees);
354 }
355 }
356
357 void handle_socket(const SocketInContext &socket)
358 {
359 if (!socket->is_available()) {
360 return;
361 }
362 if (value_by_socket_.contains(socket)) {
363 /* The socket already has a value, so there is nothing to do. */
364 return;
365 }
366 if (socket->is_input()) {
367 this->handle_input_socket(socket);
368 }
369 else {
370 this->handle_output_socket(socket);
371 }
372 }
373
374 void handle_input_socket(const SocketInContext &socket)
375 {
376 /* Multi-inputs are not supported in shader nodes currently. */
377 BLI_assert(!socket->is_multi_input());
378
379 const bNodeLink *used_link = nullptr;
380 for (const bNodeLink *link : socket->directly_linked_links()) {
381 if (!link->is_used()) {
382 continue;
383 }
384 used_link = link;
385 }
386 if (!used_link) {
387 /* If there is no link on the input, use the value of the socket directly. */
388 if (this->input_socket_may_have_dangling_value(socket)) {
389 this->store_socket_value(socket, {DanglingValue{}});
390 }
391 else {
392 this->store_socket_value(socket, {InputSocketValue{socket.socket}});
393 }
394 return;
395 }
396
397 const ComputeContext *from_context = this->get_link_source_context(*used_link, socket);
398 const SocketInContext origin_socket = {from_context, used_link->fromsock};
399 if (const auto *value = value_by_socket_.lookup_ptr(origin_socket)) {
400 if (std::holds_alternative<DanglingValue>(value->value)) {
401 if (this->input_socket_may_have_dangling_value(socket)) {
402 this->store_socket_value(socket, {DanglingValue{}});
403 }
404 else {
405 /* If the input value is dangling, use the value of the socket itself. */
406 this->store_socket_value(socket, {InputSocketValue{socket.socket}});
407 }
408 return;
409 }
410 /* If the socket linked to the input has a value already, copy that value to the current
411 * socket, potentially with an implicit conversion. */
412 this->store_socket_value(socket,
413 this->handle_implicit_conversion(*value,
414 *used_link->fromsock->typeinfo,
415 *used_link->tosock->typeinfo));
416 return;
417 }
418 /* If the origin socket does not have a value yet, only schedule it for evaluation for now.*/
419 this->schedule_socket(origin_socket);
420 }
421
427 bool input_socket_may_have_dangling_value(const SocketInContext &socket)
428 {
429 BLI_assert(socket->is_input());
430 const NodeInContext node = socket.owner_node();
431 return node->is_reroute() || node->is_muted();
432 }
433
434 const ComputeContext *get_link_source_context(const bNodeLink &link,
435 const SocketInContext &to_socket)
436 {
437 const bNodeTree &tree = to_socket->owner_tree();
438 const bke::bNodeTreeZones *zones = tree.zones();
439 if (!zones) {
440 return nullptr;
441 }
442 const bke::bNodeTreeZone *to_zone = zones->get_zone_by_socket(*to_socket);
443 const bke::bNodeTreeZone *from_zone = zones->get_zone_by_socket(*link.fromsock);
444 const ComputeContext *context = to_socket.context;
445 for (const bke::bNodeTreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone) {
446 const bNode &zone_output_node = *zone->output_node();
447 if (zone_output_node.is_type("GeometryNodeRepeatOutput")) {
448 if (this->should_preserve_repeat_zone_node(zone_output_node)) {
449 /* Preserved repeat zones are embedded into their outer compute context. */
450 continue;
451 }
452 }
453 context = parent_zone_contexts_.lookup(context);
454 }
455 return context;
456 }
457
458 void handle_output_socket(const SocketInContext &socket)
459 {
460 const NodeInContext node = socket.owner_node();
461 if (node->is_reroute()) {
462 this->handle_output_socket__reroute(socket);
463 return;
464 }
465 if (node->is_muted()) {
466 if (!this->handle_output_socket__internal_links(socket)) {
467 /* The output socket does not have a corresponding input, so the value is ignored. */
468 this->store_socket_value_dangling(socket);
469 }
470 return;
471 }
472 if (node->is_group()) {
473 this->handle_output_socket__group(socket);
474 return;
475 }
476 if (node->is_group_input()) {
477 this->handle_output_socket__group_input(socket);
478 return;
479 }
480 if (node->is_type("GeometryNodeRepeatOutput")) {
481 if (this->should_preserve_repeat_zone_node(*node)) {
482 this->handle_output_socket__preserved_repeat_output(socket);
483 return;
484 }
485 this->handle_output_socket__repeat_output(socket);
486 return;
487 }
488 if (node->is_type("GeometryNodeRepeatInput")) {
489 if (this->should_preserve_repeat_zone_node(*node)) {
490 this->handle_output_socket__preserved_repeat_input(socket);
491 return;
492 }
493 this->handle_output_socket__repeat_input(socket);
494 return;
495 }
496 if (node->is_type("NodeClosureOutput")) {
497 this->handle_output_socket__closure_output(socket);
498 return;
499 }
500 if (node->is_type("NodeClosureInput")) {
501 this->handle_output_socket__closure_input(socket);
502 return;
503 }
504 if (node->is_type("NodeEvaluateClosure")) {
505 this->handle_output_socket__evaluate_closure(socket);
506 return;
507 }
508 if (node->is_type("NodeCombineBundle")) {
509 this->handle_output_socket__combine_bundle(socket);
510 return;
511 }
512 if (node->is_type("NodeSeparateBundle")) {
513 this->handle_output_socket__separate_bundle(socket);
514 return;
515 }
516 if (node->is_type("GeometryNodeMenuSwitch")) {
517 this->handle_output_socket__menu_switch(socket);
518 return;
519 }
520 this->handle_output_socket__eval(socket);
521 }
522
523 void handle_output_socket__reroute(const SocketInContext &socket)
524 {
525 const NodeInContext node = socket.owner_node();
526 const SocketInContext input_socket = node.input_socket(0);
527 this->forward_value_or_schedule(socket, input_socket);
528 }
529
530 /* Returns whether the socket was handled. */
531 [[nodiscard]] bool handle_output_socket__internal_links(const SocketInContext &socket)
532 {
533 const NodeInContext node = socket.owner_node();
534 for (const bNodeLink &internal_link : node->internal_links()) {
535 if (internal_link.tosock == socket.socket) {
536 const SocketInContext src_socket = {socket.context, internal_link.fromsock};
537 if (const SocketValue *value = value_by_socket_.lookup_ptr(src_socket)) {
538 /* Pass the value of the internally linked input socket, with an implicit conversion if
539 * necessary. */
540 this->store_socket_value(
541 socket,
542 this->handle_implicit_conversion(
543 *value, *internal_link.fromsock->typeinfo, *internal_link.tosock->typeinfo));
544 return true;
545 }
546 this->schedule_socket(src_socket);
547 return true;
548 }
549 }
550 return false;
551 }
552
553 void handle_output_socket__group(const SocketInContext &socket)
554 {
555 const NodeInContext node = socket.owner_node();
556 const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node->id);
557 if (!group || ID_MISSING(&group->id)) {
558 this->store_socket_value_fallback(socket);
559 return;
560 }
561 group->ensure_interface_cache();
562 group->ensure_topology_cache();
563 const bNode *group_output_node = group->group_output_node();
564 if (!group_output_node) {
565 this->store_socket_value_fallback(socket);
566 return;
567 }
568 /* Get the value of an output of a group node by evaluating the corresponding output of the
569 * node group. Since this socket is in a different tree, the compute context is different. */
570 const ComputeContext &group_compute_context = compute_context_cache_.for_group_node(
571 socket.context, node->identifier, &node->owner_tree());
572 const SocketInContext group_output_socket_ctx = {
573 &group_compute_context, &group_output_node->input_socket(socket->index())};
574 this->forward_value_or_schedule(socket, group_output_socket_ctx);
575 }
576
577 void handle_output_socket__group_input(const SocketInContext &socket)
578 {
579 if (const auto *group_node_compute_context =
580 dynamic_cast<const bke::GroupNodeComputeContext *>(socket.context))
581 {
582 /* Get the value of a group input from the corresponding input socket of the parent group
583 * node. */
584 const ComputeContext *parent_compute_context = group_node_compute_context->parent();
585 const bNode *group_node = group_node_compute_context->node();
586 BLI_assert(group_node);
587 const bNodeSocket &group_node_input = group_node->input_socket(socket->index());
588 const SocketInContext group_input_socket_ctx = {parent_compute_context, &group_node_input};
589 this->forward_value_or_schedule(socket, group_input_socket_ctx);
590 return;
591 }
592 this->store_socket_value_fallback(socket);
593 }
594
595 bool should_preserve_repeat_zone_node(const bNode &repeat_zone_node) const
596 {
597 BLI_assert(repeat_zone_node.is_type("GeometryNodeRepeatOutput") ||
598 repeat_zone_node.is_type("GeometryNodeRepeatInput"));
599 if (!params_.allow_preserving_repeat_zones) {
600 return false;
601 }
602 const bNodeTree &tree = repeat_zone_node.owner_tree();
603 const bke::bNodeTreeZones *zones = tree.zones();
604 if (!zones) {
605 return false;
606 }
607 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(repeat_zone_node.identifier);
608 if (!zone) {
609 return false;
610 }
611 const bNode *repeat_zone_input_node = zone->input_node();
612 const bNode *repeat_zone_output_node = zone->output_node();
613 if (!repeat_zone_input_node || !repeat_zone_output_node) {
614 return false;
615 }
616 const auto &storage = *static_cast<const NodeGeometryRepeatOutput *>(
617 repeat_zone_output_node->storage);
618 for (const int i : IndexRange(storage.items_num)) {
619 const NodeRepeatItem &item = storage.items[i];
621 /* Repeat zones with more special types have to be inlined. */
622 return false;
623 }
624 }
625 return true;
626 }
627
628 void handle_output_socket__repeat_output(const SocketInContext &socket)
629 {
630 const bNode &repeat_output_node = socket->owner_node();
631 const bNodeTree &tree = socket->owner_tree();
632
633 const bke::bNodeTreeZones *zones = tree.zones();
634 if (!zones) {
635 this->store_socket_value_fallback(socket);
636 return;
637 }
638 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(repeat_output_node.identifier);
639 if (!zone) {
640 this->store_socket_value_fallback(socket);
641 return;
642 }
643 const NodeInContext repeat_input_node = {socket.context, zone->input_node()};
644 const SocketInContext iterations_input = repeat_input_node.input_socket(0);
645 const SocketValue *iterations_socket_value = value_by_socket_.lookup_ptr(iterations_input);
646 if (!iterations_socket_value) {
647 /* The number of iterations is not known yet, so only schedule that socket for now. */
648 this->schedule_socket(iterations_input);
649 return;
650 }
651 const std::optional<PrimitiveSocketValue> iterations_value_opt =
652 iterations_socket_value->to_primitive(*iterations_input->typeinfo);
653 if (!iterations_value_opt) {
654 this->add_dynamic_repeat_zone_iterations_error(*repeat_input_node);
655 }
656 const int iterations = iterations_value_opt.has_value() ?
657 std::get<int>(iterations_value_opt->value) :
658 0;
659 if (iterations <= 0) {
660 /* If the number of iterations is zero, the values are copied directly from the repeat input
661 * node. */
662 const SocketInContext origin_socket = repeat_input_node.input_socket(1 + socket->index());
663 this->forward_value_or_schedule(socket, origin_socket);
664 return;
665 }
666 /* Otherwise, the value is copied from the output of the last iteration. */
667 const ComputeContext &last_iteration_context = compute_context_cache_.for_repeat_zone(
668 socket.context, repeat_output_node, iterations - 1);
669 parent_zone_contexts_.add(&last_iteration_context, socket.context);
670 const SocketInContext origin_socket = {&last_iteration_context,
671 &repeat_output_node.input_socket(socket->index())};
672 this->forward_value_or_schedule(socket, origin_socket);
673 }
674
675 void handle_output_socket__preserved_repeat_output(const SocketInContext &socket)
676 {
677 const bNodeTree &tree = socket->owner_tree();
678 const NodeInContext repeat_output_node = socket.owner_node();
679 const bke::bNodeTreeZones &zones = *tree.zones();
680 const bke::bNodeTreeZone &zone = *zones.get_zone_by_node(repeat_output_node->identifier);
681 const bNode &repeat_input_node = *zone.input_node();
682
683 const EnsureInputsResult ensured_inputs = this->ensure_node_inputs(socket.owner_node());
684 if (ensured_inputs.has_missing_inputs) {
685 /* The node can only be evaluated if all inputs values are known. */
686 return;
687 }
688 const NodeInContext node = socket.owner_node();
689 bNode &copied_node = this->handle_output_socket__eval_copy_node(node);
690 PreservedZone &preserved_zone = copied_zone_by_zone_output_node_.lookup_or_add_default(
691 repeat_output_node);
692 preserved_zone.output_node = &copied_node;
693 /* Ensure that the repeat input node is created as well. */
694 this->schedule_socket({node.context, &repeat_input_node.output_socket(0)});
695 }
696
697 void handle_output_socket__preserved_repeat_input(const SocketInContext &socket)
698 {
699 const EnsureInputsResult ensured_inputs = this->ensure_node_inputs(socket.owner_node());
700 if (ensured_inputs.has_missing_inputs) {
701 /* The node can only be evaluated if all inputs values are known. */
702 return;
703 }
704 const bNodeTree &tree = socket->owner_tree();
705 const NodeInContext node = socket.owner_node();
706 bNode &copied_node = this->handle_output_socket__eval_copy_node(node);
707 const auto &storage = *static_cast<const NodeGeometryRepeatInput *>(node->storage);
708 const NodeInContext repeat_output_node{node.context, tree.node_by_id(storage.output_node_id)};
709 PreservedZone &preserved_zone = copied_zone_by_zone_output_node_.lookup_or_add_default(
710 repeat_output_node);
711 preserved_zone.input_node = &copied_node;
712 }
713
714 void add_dynamic_repeat_zone_iterations_error(const bNode &repeat_input_node)
715 {
716 params_.r_error_messages.append(
717 {&repeat_input_node, TIP_("Iterations input has to be a constant value")});
718 }
719
720 void handle_output_socket__repeat_input(const SocketInContext &socket)
721 {
722 const bNode &repeat_input_node = socket->owner_node();
723 const auto *repeat_zone_context = dynamic_cast<const bke::RepeatZoneComputeContext *>(
724 socket.context);
725 if (!repeat_zone_context) {
726 this->store_socket_value_fallback(socket);
727 return;
728 }
729 /* The index of the current iteration comes from the context. */
730 const int iteration = repeat_zone_context->iteration();
731
732 if (socket->index() == 0) {
733 /* The first output is the current iteration index. */
734 this->store_socket_value(socket, {PrimitiveSocketValue{iteration}});
735 return;
736 }
737
738 if (iteration == 0) {
739 /* In the first iteration, the values are copied from the corresponding input socket. */
740 const SocketInContext origin_socket = {repeat_zone_context->parent(),
741 &repeat_input_node.input_socket(socket->index())};
742 this->forward_value_or_schedule(socket, origin_socket);
743 return;
744 }
745 /* For later iterations, the values are copied from the corresponding output of the previous
746 * iteration. */
747 const bNode &repeat_output_node = *repeat_input_node.owner_tree().node_by_id(
748 repeat_zone_context->output_node_id());
749 const int previous_iteration = iteration - 1;
750 const ComputeContext &previous_iteration_context = compute_context_cache_.for_repeat_zone(
751 repeat_zone_context->parent(), repeat_output_node, previous_iteration);
752 parent_zone_contexts_.add(&previous_iteration_context, repeat_zone_context->parent());
753 const SocketInContext origin_socket = {&previous_iteration_context,
754 &repeat_output_node.input_socket(socket->index() - 1)};
755 this->forward_value_or_schedule(socket, origin_socket);
756 }
757
758 void handle_output_socket__closure_output(const SocketInContext &socket)
759 {
760 const bNode &node = socket->owner_node();
761 const bke::bNodeTreeZones *zones = node.owner_tree().zones();
762 if (!zones) {
763 this->store_socket_value_fallback(socket);
764 return;
765 }
766 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(node.identifier);
767 if (!zone) {
768 this->store_socket_value_fallback(socket);
769 return;
770 }
771 /* Just store a reference to the closure. */
772 this->store_socket_value(socket, {ClosureZoneValue{zone, socket.context}});
773 }
774
775 void handle_output_socket__evaluate_closure(const SocketInContext &socket)
776 {
777 const NodeInContext evaluate_closure_node = socket.owner_node();
778 const SocketInContext closure_input_socket = evaluate_closure_node.input_socket(0);
779 const SocketValue *closure_input_value = value_by_socket_.lookup_ptr(closure_input_socket);
780 if (!closure_input_value) {
781 /* The closure to evaluate is not known yet, so schedule the closure input before it can be
782 * evaluated. */
783 this->schedule_socket(closure_input_socket);
784 return;
785 }
786 const ClosureZoneValue *closure_zone_value = std::get_if<ClosureZoneValue>(
787 &closure_input_value->value);
788 if (!closure_zone_value) {
789 /* If the closure is null, the node behaves as if it is muted. */
790 if (!this->handle_output_socket__internal_links(socket)) {
791 this->store_socket_value_fallback(socket);
792 }
793 return;
794 }
795 const auto *evaluate_closure_storage = static_cast<const NodeEvaluateClosure *>(
796 evaluate_closure_node->storage);
797 const bNode &closure_output_node = *closure_zone_value->zone->output_node();
798 const auto &closure_storage = *static_cast<const NodeClosureOutput *>(
799 closure_output_node.storage);
800 const StringRef key = evaluate_closure_storage->output_items.items[socket->index()].name;
801
802 const ClosureSourceLocation closure_source_location{
803 &closure_output_node.owner_tree(),
804 closure_output_node.identifier,
805 closure_zone_value->closure_creation_context ?
806 closure_zone_value->closure_creation_context->hash() :
807 ComputeContextHash{},
808 closure_zone_value->closure_creation_context};
809 const bke::EvaluateClosureComputeContext &closure_eval_context =
810 compute_context_cache_.for_evaluate_closure(socket.context,
811 evaluate_closure_node->identifier,
812 &socket->owner_tree(),
813 closure_source_location);
814 parent_zone_contexts_.add(&closure_eval_context, closure_zone_value->closure_creation_context);
815
816 if (closure_eval_context.is_recursive()) {
817 this->store_socket_value_fallback(socket);
818 params_.r_error_messages.append(
819 {&*evaluate_closure_node, TIP_("Recursive closures are not supported")});
820 return;
821 }
822
823 for (const int i : IndexRange(closure_storage.output_items.items_num)) {
824 const NodeClosureOutputItem &item = closure_storage.output_items.items[i];
825 if (key != item.name) {
826 continue;
827 }
828 /* Get the value of the output by evaluating the corresponding output in the closure zone. */
829 const SocketInContext origin_socket = {&closure_eval_context,
830 &closure_output_node.input_socket(i)};
831 this->forward_value_or_schedule(socket, origin_socket);
832 return;
833 }
834 this->store_socket_value_fallback(socket);
835 }
836
837 void handle_output_socket__closure_input(const SocketInContext &socket)
838 {
839 const bNode &closure_input_node = socket->owner_node();
840 const auto *closure_eval_context = dynamic_cast<const bke::EvaluateClosureComputeContext *>(
841 socket.context);
842 if (!closure_eval_context) {
843 this->store_socket_value_fallback(socket);
844 return;
845 }
846 const bNode &closure_output_node = *closure_input_node.owner_tree().node_by_id(
847 closure_eval_context->closure_source_location()->closure_output_node_id);
848 const NodeInContext closure_eval_node = {closure_eval_context->parent(),
849 closure_eval_context->node()};
850
851 const auto &closure_storage = *static_cast<const NodeClosureOutput *>(
852 closure_output_node.storage);
853 const auto &eval_closure_storage = *static_cast<const NodeEvaluateClosure *>(
854 closure_eval_node->storage);
855
856 const StringRef key = closure_storage.input_items.items[socket->index()].name;
857 for (const int i : IndexRange(eval_closure_storage.input_items.items_num)) {
858 const NodeEvaluateClosureInputItem &item = eval_closure_storage.input_items.items[i];
859 if (key != item.name) {
860 continue;
861 }
862 /* The input of a closure zone gets its value from the corresponding input of the Evaluate
863 * Closure node that evaluates it. */
864 const SocketInContext origin_socket = closure_eval_node.input_socket(i + 1);
865 this->forward_value_or_schedule(socket, origin_socket);
866 return;
867 }
868 this->store_socket_value_fallback(socket);
869 }
870
871 void handle_output_socket__combine_bundle(const SocketInContext &socket)
872 {
873 const NodeInContext node = socket.owner_node();
874 const auto &storage = *static_cast<const NodeCombineBundle *>(node->storage);
875
876 bool all_inputs_available = true;
877 for (const bNodeSocket *input_socket : node->input_sockets()) {
878 const SocketInContext input_socket_ctx = {socket.context, input_socket};
879 if (!value_by_socket_.lookup_ptr(input_socket_ctx)) {
880 this->schedule_socket(input_socket_ctx);
881 all_inputs_available = false;
882 }
883 }
884 if (!all_inputs_available) {
885 /* Can't create the bundle yet. Wait until all inputs are available. */
886 return;
887 }
888 /* Build the actual bundle socket value from the input values. */
889 auto bundle_value = std::make_shared<BundleSocketValue>();
890 for (const int i : IndexRange(storage.items_num)) {
891 const SocketInContext input_socket = node.input_socket(i);
892 const NodeCombineBundleItem &item = storage.items[i];
893 const StringRef key = item.name;
894 const auto &socket_value = value_by_socket_.lookup(input_socket);
895 bundle_value->items.append({key, socket_value, input_socket->typeinfo});
896 }
897 this->store_socket_value(socket, {bundle_value});
898 }
899
900 void handle_output_socket__separate_bundle(const SocketInContext &socket)
901 {
902 const NodeInContext node = socket.owner_node();
903 const auto &storage = *static_cast<const NodeSeparateBundle *>(node->storage);
904
905 const SocketInContext input_socket = node.input_socket(0);
906 const SocketValue *socket_value = value_by_socket_.lookup_ptr(input_socket);
907 if (!socket_value) {
908 /* The input bundle is not known yet, so schedule it for now. */
909 this->schedule_socket(input_socket);
910 return;
911 }
912 const auto *bundle_value_ptr = std::get_if<BundleSocketValuePtr>(&socket_value->value);
913 if (!bundle_value_ptr) {
914 /* The bundle is empty. Use the fallback value. */
915 this->store_socket_value_fallback(socket);
916 return;
917 }
918 const BundleSocketValue &bundle_value = **bundle_value_ptr;
919
920 const StringRef key = storage.items[socket->index()].name;
921 for (const BundleSocketValue::Item &item : bundle_value.items) {
922 if (key != item.key) {
923 continue;
924 }
925 /* Extract the value from the bundle.*/
926 const SocketValue converted_value = this->handle_implicit_conversion(
927 item.value, *item.socket_type, *socket->typeinfo);
928 this->store_socket_value(socket, converted_value);
929 return;
930 }
931 /* The bundle does not contain the requested key, so use the fallback value. */
932 this->store_socket_value_fallback(socket);
933 }
934
935 void handle_output_socket__menu_switch(const SocketInContext &socket)
936 {
937 const NodeInContext node = socket.owner_node();
938 const auto &storage = *static_cast<const NodeMenuSwitch *>(node->storage);
939
940 const SocketInContext menu_input = node.input_socket(0);
941 const SocketValue *menu_socket_value = value_by_socket_.lookup_ptr(menu_input);
942 if (!menu_socket_value) {
943 /* The menu value is not known yet, so schedule it for now. */
944 this->schedule_socket(menu_input);
945 return;
946 }
947
948 const std::optional<PrimitiveSocketValue> menu_value_opt = menu_socket_value->to_primitive(
949 *menu_input->typeinfo);
950 if (!menu_value_opt) {
951 /* This limitation may be lifted in the future. Menu Switch nodes could be supported natively
952 * by render engines or we convert them to a bunch of mix nodes. */
953 this->store_socket_value_fallback(socket);
954 params_.r_error_messages.append({node.node, TIP_("Menu value has to be a constant value")});
955 return;
956 }
957 const MenuValue menu_value = std::get<MenuValue>(menu_value_opt->value);
958 /* Find the selected item index. */
959 std::optional<int> selected_index;
960 for (const int item_i : IndexRange(storage.enum_definition.items_num)) {
961 const NodeEnumItem &item = storage.enum_definition.items_array[item_i];
962 if (MenuValue(item.identifier) == menu_value) {
963 selected_index = item_i;
964 break;
965 }
966 }
967 if (!selected_index.has_value()) {
968 /* The input value does not exist in the menu. */
969 this->store_socket_value_fallback(socket);
970 return;
971 }
972 if (socket->index() == 0) {
973 /* Handle forwarding the selected value. */
974 this->forward_value_or_schedule(socket, node.input_socket(*selected_index + 1));
975 return;
976 }
977 /* Set the value of the mask output. */
978 const bool is_selected = selected_index == socket->index() - 1;
979 this->store_socket_value(socket, {PrimitiveSocketValue{is_selected}});
980 }
981
986 void handle_output_socket__eval(const SocketInContext &socket)
987 {
988 const NodeInContext node = socket.owner_node();
989 const EnsureInputsResult ensured_inputs = this->ensure_node_inputs(node);
990 if (ensured_inputs.has_missing_inputs) {
991 /* The node can only be evaluated if all inputs values are known. */
992 return;
993 }
994 const bke::bNodeType &node_type = *node->typeinfo;
995 if (node_type.build_multi_function && ensured_inputs.all_inputs_primitive) {
996 /* Do constant folding. */
997 this->handle_output_socket__eval_multi_function(node);
998 return;
999 }
1000 /* The node can't be constant-folded. So copy it to the destination tree instead. */
1001 this->handle_output_socket__eval_copy_node(node);
1002 }
1003
1004 struct EnsureInputsResult {
1005 bool has_missing_inputs = false;
1006 bool all_inputs_primitive = false;
1007 };
1008
1009 EnsureInputsResult ensure_node_inputs(const NodeInContext &node)
1010 {
1011 EnsureInputsResult result;
1012 result.has_missing_inputs = false;
1013 result.all_inputs_primitive = true;
1014 for (const bNodeSocket *input_socket : node->input_sockets()) {
1015 if (!input_socket->is_available()) {
1016 continue;
1017 }
1018 const SocketInContext input_socket_ctx = {node.context, input_socket};
1019 const SocketValue *value = value_by_socket_.lookup_ptr(input_socket_ctx);
1020 if (!value) {
1021 this->schedule_socket(input_socket_ctx);
1022 result.has_missing_inputs = true;
1023 continue;
1024 }
1025 if (!value->to_primitive(*input_socket->typeinfo)) {
1026 result.all_inputs_primitive = false;
1027 }
1028 }
1029 return result;
1030 }
1031
1032 void handle_output_socket__eval_multi_function(const NodeInContext &node)
1033 {
1034 NodeMultiFunctionBuilder builder{*node.node, node->owner_tree()};
1035 node->typeinfo->build_multi_function(builder);
1036 const mf::MultiFunction &fn = builder.function();
1037 mf::ContextBuilder context;
1038 IndexMask mask(1);
1039 mf::ParamsBuilder params{fn, &mask};
1040
1041 /* Prepare inputs to the multi-function evaluation. */
1042 for (const bNodeSocket *input_socket : node->input_sockets()) {
1043 if (!input_socket->is_available()) {
1044 continue;
1045 }
1046 const SocketInContext input_socket_ctx = {node.context, input_socket};
1047 const PrimitiveSocketValue value =
1048 *value_by_socket_.lookup(input_socket_ctx).to_primitive(*input_socket->typeinfo);
1049 params.add_readonly_single_input(
1050 GVArray::from_single(*input_socket->typeinfo->base_cpp_type, 1, value.buffer()));
1051 }
1052
1053 /* Prepare output buffers. */
1054 Vector<void *> output_values;
1055 for (const bNodeSocket *output_socket : node->output_sockets()) {
1056 if (!output_socket->is_available()) {
1057 continue;
1058 }
1059 void *value = scope_.allocate_owned(*output_socket->typeinfo->base_cpp_type);
1060 output_values.append(value);
1061 params.add_uninitialized_single_output(
1062 GMutableSpan(output_socket->typeinfo->base_cpp_type, value, 1));
1063 }
1064
1065 fn.call(mask, params, context);
1066
1067 /* Store constant-folded values for the output sockets. */
1068 int current_output_i = 0;
1069 for (const bNodeSocket *output_socket : node->output_sockets()) {
1070 if (!output_socket->is_available()) {
1071 continue;
1072 }
1073 const void *value = output_values[current_output_i++];
1074 this->store_socket_value(
1075 {node.context, output_socket},
1076 {PrimitiveSocketValue::from_value({output_socket->typeinfo->base_cpp_type, value})});
1077 }
1078 }
1079
1080 bNode &handle_output_socket__eval_copy_node(const NodeInContext &node)
1081 {
1082 Map<const bNodeSocket *, bNodeSocket *> socket_map;
1083 /* We generate our own identifier and name here to get unique values without having to scan all
1084 * already existing nodes. */
1085 const int identifier = this->get_next_node_identifier();
1086 const std::string unique_name = fmt::format("{}_{}", identifier, node.node->name);
1087 bNode &copied_node = *bke::node_copy_with_mapping(
1088 &dst_tree_,
1089 *node.node,
1090 this->node_copy_flag(),
1091 unique_name.size() < sizeof(bNode::name) ? std::make_optional<StringRefNull>(unique_name) :
1092 std::nullopt,
1093 identifier,
1094 socket_map);
1095
1096 /* Clear the parent frame pointer, because it does not exist in the destination tree. */
1097 copied_node.parent = nullptr;
1098
1099 /* Setup input sockets for the copied node. */
1100 for (const bNodeSocket *src_input_socket : node->input_sockets()) {
1101 if (!src_input_socket->is_available()) {
1102 continue;
1103 }
1104 bNodeSocket &dst_input_socket = *socket_map.lookup(src_input_socket);
1105 const SocketInContext input_socket_ctx = {node.context, src_input_socket};
1106 const SocketValue &value = value_by_socket_.lookup(input_socket_ctx);
1107 this->set_input_socket_value(*node, copied_node, dst_input_socket, value);
1108 }
1109 for (const bNodeSocket *src_output_socket : node->output_sockets()) {
1110 if (!src_output_socket->is_available()) {
1111 continue;
1112 }
1113 bNodeSocket &dst_output_socket = *socket_map.lookup(src_output_socket);
1114 const SocketInContext output_socket_ctx = {node.context, src_output_socket};
1115 this->store_socket_value(output_socket_ctx,
1116 {LinkedSocketValue{&copied_node, &dst_output_socket}});
1117 }
1118 return copied_node;
1119 }
1120
1122 SocketValue handle_implicit_conversion(const SocketValue &src_value,
1123 const bke::bNodeSocketType &from_socket_type,
1124 const bke::bNodeSocketType &to_socket_type)
1125 {
1126 if (from_socket_type.type == to_socket_type.type) {
1127 return src_value;
1128 }
1129 if (std::get_if<LinkedSocketValue>(&src_value.value)) {
1130 return src_value;
1131 }
1132 if (std::get_if<DanglingValue>(&src_value.value)) {
1133 return src_value;
1134 }
1135 const std::optional<PrimitiveSocketValue> src_primitive_value = src_value.to_primitive(
1136 from_socket_type);
1137 if (src_primitive_value && to_socket_type.base_cpp_type) {
1138 if (data_type_conversions_.is_convertible(*from_socket_type.base_cpp_type,
1139 *to_socket_type.base_cpp_type))
1140 {
1141 const void *src_buffer = src_primitive_value->buffer();
1142 BUFFER_FOR_CPP_TYPE_VALUE(*to_socket_type.base_cpp_type, dst_buffer);
1143 data_type_conversions_.convert_to_uninitialized(*from_socket_type.base_cpp_type,
1144 *to_socket_type.base_cpp_type,
1145 src_buffer,
1146 dst_buffer);
1147 return {
1148 PrimitiveSocketValue::from_value(GPointer{to_socket_type.base_cpp_type, dst_buffer})};
1149 }
1150 }
1151 if (src_primitive_value && to_socket_type.type == SOCK_SHADER) {
1152 /* Insert a Color node when converting a primitive value to a shader. */
1153 bNode *color_node = this->add_node("ShaderNodeRGB");
1154 const void *src_buffer = src_primitive_value->buffer();
1155 ColorGeometry4f color;
1156 data_type_conversions_.convert_to_uninitialized(
1157 *from_socket_type.base_cpp_type, CPPType::get<ColorGeometry4f>(), src_buffer, &color);
1158 bNodeSocket *output_socket = static_cast<bNodeSocket *>(color_node->outputs.first);
1159 auto *socket_storage = static_cast<bNodeSocketValueRGBA *>(output_socket->default_value);
1160 copy_v3_v3(socket_storage->value, color);
1161 socket_storage->value[3] = 1.0f;
1162 return {LinkedSocketValue{color_node, output_socket}};
1163 }
1164
1165 return SocketValue{FallbackValue{}};
1166 }
1167
1168 void set_input_socket_value(const bNode &original_node,
1169 bNode &dst_node,
1170 bNodeSocket &dst_socket,
1171 const SocketValue &value)
1172 {
1173 BLI_assert(dst_socket.is_input());
1174 if (dst_socket.flag & SOCK_HIDE_VALUE) {
1175 if (const auto *input_socket_value = std::get_if<InputSocketValue>(&value.value)) {
1176 if (input_socket_value->socket->flag & SOCK_HIDE_VALUE) {
1177 /* Don't add a value or link of the source and destination sockets don't have a value. */
1178 return;
1179 }
1180 }
1181 }
1182 if (const std::optional<PrimitiveSocketValue> primitive_value = value.to_primitive(
1183 *dst_socket.typeinfo))
1184 {
1185 if (dst_socket.flag & SOCK_HIDE_VALUE) {
1186 /* Can't store the primitive value directly on the socket. So create a new input node and
1187 * link it instead. */
1188 const NodeAndSocket node_and_socket = this->primitive_value_to_output_socket(
1189 *primitive_value);
1190 if (dst_tree_.typeinfo->validate_link(node_and_socket.socket->typeinfo->type,
1191 dst_socket.typeinfo->type))
1192 {
1194 dst_tree_, *node_and_socket.node, *node_and_socket.socket, dst_node, dst_socket);
1195 }
1196 }
1197 else {
1198 this->set_primitive_value_on_socket(dst_socket, *primitive_value);
1199 }
1200 return;
1201 }
1202 if (!params_.allow_preserving_repeat_zones) {
1203 const bool is_iterations_input = dst_node.inputs.first == &dst_socket &&
1204 dst_node.is_type("GeometryNodeRepeatInput");
1205 if (is_iterations_input) {
1206 this->add_dynamic_repeat_zone_iterations_error(original_node);
1207 this->set_primitive_value_on_socket(dst_socket, PrimitiveSocketValue{0});
1208 return;
1209 }
1210 }
1211 if (std::get_if<InputSocketValue>(&value.value)) {
1212 /* Cases were the input has a primitive value are handled above. */
1213 return;
1214 }
1215 if (std::get_if<FallbackValue>(&value.value)) {
1216 /* Cases were the input has a primitive fallback value are handled above. */
1217 return;
1218 }
1219 if (std::get_if<DanglingValue>(&value.value)) {
1220 /* Input sockets should never have a dangling value, because they are replaced by the socket
1221 * value in #handle_input_socket. */
1223 return;
1224 }
1225 if (std::get_if<BundleSocketValuePtr>(&value.value)) {
1226 /* This type can't be assigned to a socket. The bundle has to be separated first. */
1228 return;
1229 }
1230 if (std::get_if<ClosureZoneValue>(&value.value)) {
1231 /* This type can't be assigned to a socket. One has to evaluate a closure. */
1233 return;
1234 }
1235 if (const auto *src_socket_value = std::get_if<LinkedSocketValue>(&value.value)) {
1236 if (dst_tree_.typeinfo->validate_link(src_socket_value->socket->typeinfo->type,
1237 dst_socket.typeinfo->type))
1238 {
1240 dst_tree_, *src_socket_value->node, *src_socket_value->socket, dst_node, dst_socket);
1241 }
1242 return;
1243 }
1245 }
1246
1247 NodeAndSocket primitive_value_to_output_socket(const PrimitiveSocketValue &value)
1248 {
1249 if (const float *value_float = std::get_if<float>(&value.value)) {
1250 bNode *node = this->add_node("ShaderNodeValue");
1251 bNodeSocket *socket = static_cast<bNodeSocket *>(node->outputs.first);
1252 socket->default_value_typed<bNodeSocketValueFloat>()->value = *value_float;
1253 return {node, socket};
1254 }
1255 if (const int *value_int = std::get_if<int>(&value.value)) {
1256 bNode *node = this->add_node("ShaderNodeValue");
1257 bNodeSocket *socket = static_cast<bNodeSocket *>(node->outputs.first);
1258 socket->default_value_typed<bNodeSocketValueFloat>()->value = *value_int;
1259 return {node, socket};
1260 }
1261 if (const bool *value_bool = std::get_if<bool>(&value.value)) {
1262 bNode *node = this->add_node("ShaderNodeValue");
1263 bNodeSocket *socket = static_cast<bNodeSocket *>(node->outputs.first);
1264 socket->default_value_typed<bNodeSocketValueFloat>()->value = *value_bool;
1265 return {node, socket};
1266 }
1267 if (const float3 *value_float3 = std::get_if<float3>(&value.value)) {
1268 bNode *node = this->add_node("ShaderNodeCombineXYZ");
1269 bNodeSocket *output_socket = static_cast<bNodeSocket *>(node->outputs.first);
1270 bNodeSocket *input_x = static_cast<bNodeSocket *>(node->inputs.first);
1271 bNodeSocket *input_y = input_x->next;
1272 bNodeSocket *input_z = input_y->next;
1273 input_x->default_value_typed<bNodeSocketValueFloat>()->value = value_float3->x;
1274 input_y->default_value_typed<bNodeSocketValueFloat>()->value = value_float3->y;
1275 input_z->default_value_typed<bNodeSocketValueFloat>()->value = value_float3->z;
1276 return {node, output_socket};
1277 }
1278 if (const ColorGeometry4f *value_color = std::get_if<ColorGeometry4f>(&value.value)) {
1279 bNode *node = this->add_node("ShaderNodeRGB");
1280 bNodeSocket *output_socket = static_cast<bNodeSocket *>(node->outputs.first);
1281 auto *socket_storage = static_cast<bNodeSocketValueRGBA *>(output_socket->default_value);
1282 copy_v3_v3(socket_storage->value, *value_color);
1283 socket_storage->value[3] = 1.0f;
1284 return {node, output_socket};
1285 }
1287 return {};
1288 }
1289
1290 bNode *add_node(const StringRefNull idname)
1291 {
1292 return bke::node_add_node(nullptr, dst_tree_, idname, this->get_next_node_identifier());
1293 }
1294
1295 int get_next_node_identifier()
1296 {
1297 return ++dst_node_counter_;
1298 }
1299
1300 void set_primitive_value_on_socket(bNodeSocket &socket, const PrimitiveSocketValue &value)
1301 {
1302 switch (socket.type) {
1303 case SOCK_FLOAT: {
1304 socket.default_value_typed<bNodeSocketValueFloat>()->value = std::get<float>(value.value);
1305 break;
1306 }
1307 case SOCK_INT: {
1308 socket.default_value_typed<bNodeSocketValueInt>()->value = std::get<int>(value.value);
1309 break;
1310 }
1311 case SOCK_BOOLEAN: {
1312 socket.default_value_typed<bNodeSocketValueBoolean>()->value = std::get<bool>(value.value);
1313 break;
1314 }
1315 case SOCK_VECTOR: {
1316 copy_v3_v3(socket.default_value_typed<bNodeSocketValueVector>()->value,
1317 std::get<float3>(value.value));
1318 break;
1319 }
1320 case SOCK_RGBA: {
1321 copy_v4_v4(socket.default_value_typed<bNodeSocketValueRGBA>()->value,
1322 std::get<ColorGeometry4f>(value.value));
1323 break;
1324 }
1325 default: {
1327 break;
1328 }
1329 }
1330 }
1331
1332 void restore_zones_in_output_tree()
1333 {
1334 for (const PreservedZone &copied_zone : copied_zone_by_zone_output_node_.values()) {
1335 if (!copied_zone.input_node || !copied_zone.output_node) {
1336 continue;
1337 }
1338 const bke::bNodeZoneType *zone_type = bke::zone_type_by_node_type(
1339 copied_zone.input_node->type_legacy);
1340 if (!zone_type) {
1341 continue;
1342 }
1343 int &output_id = zone_type->get_corresponding_output_id(*copied_zone.input_node);
1344 output_id = copied_zone.output_node->identifier;
1345 }
1346 }
1347
1348 void position_nodes_in_output_tree()
1349 {
1350 bNodeTree &tree = dst_tree_;
1351 tree.ensure_topology_cache();
1352
1353 Map<int, int> num_by_depth;
1354 Map<bNode *, int> depth_by_node;
1355
1356 /* Simple algorithm that does a very rough layout of the generated tree. This does not produce
1357 * great results generally, but is usually good enough when debugging smaller node trees. */
1358 for (bNode *node : tree.toposort_right_to_left()) {
1359 int depth = 0;
1360 for (bNodeSocket *socket : node->output_sockets()) {
1361 for (bNodeSocket *target : socket->directly_linked_sockets()) {
1362 depth = std::max(depth, depth_by_node.lookup(&target->owner_node()) + 1);
1363 }
1364 }
1365 depth_by_node.add_new(node, depth);
1366 const int index_at_depth = num_by_depth.lookup_or_add(depth, 0)++;
1367 node->location[0] = 200 - depth * 200;
1368 node->location[1] = -index_at_depth * 300;
1369 }
1370 }
1371
1376 void forward_value_or_schedule(const SocketInContext &socket, const SocketInContext &origin)
1377 {
1378 if (const SocketValue *value = value_by_socket_.lookup_ptr(origin)) {
1379 if (socket->type == origin->type) {
1380 this->store_socket_value(socket, *value);
1381 return;
1382 }
1383 this->store_socket_value(
1384 socket, this->handle_implicit_conversion(*value, *origin->typeinfo, *socket->typeinfo));
1385 return;
1386 }
1387 this->schedule_socket(origin);
1388 }
1389
1390 void store_socket_value(const SocketInContext &socket, SocketValue value)
1391 {
1392 value_by_socket_.add_new(socket, std::move(value));
1393 }
1394
1395 void store_socket_value_fallback(const SocketInContext &socket)
1396 {
1397 value_by_socket_.add_new(socket, {FallbackValue{}});
1398 }
1399
1400 void store_socket_value_dangling(const SocketInContext &socket)
1401 {
1402 value_by_socket_.add_new(socket, {DanglingValue{}});
1403 }
1404
1405 void schedule_socket(const SocketInContext &socket)
1406 {
1407 scheduled_sockets_stack_.push(socket);
1408 }
1409
1410 int node_copy_flag() const
1411 {
1412 const bool use_refcounting = !(dst_tree_.id.tag & ID_TAG_NO_MAIN);
1413 return use_refcounting ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT;
1414 }
1415};
1416
1417} // namespace
1418
1420 bNodeTree &dst_tree,
1422{
1423 ShaderNodesInliner inliner(src_tree, dst_tree, params);
1424
1425 if (inliner.do_inline()) {
1426 /* Update deprecated bNodeSocket.link pointers because some code still depends on it. */
1427 LISTBASE_FOREACH (bNode *, node, &dst_tree.nodes) {
1428 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1429 sock->link = nullptr;
1430 }
1431 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1432 sock->link = nullptr;
1433 }
1434 }
1435 LISTBASE_FOREACH (bNodeLink *, link, &dst_tree.links) {
1436 link->tosock->link = link;
1437 BLI_assert(dst_tree.typeinfo->validate_link(link->fromsock->typeinfo->type,
1438 link->tosock->typeinfo->type));
1439 link->flag |= NODE_LINK_VALID;
1440 }
1441 return true;
1442 }
1443
1444 return false;
1445}
1446
1447} // namespace blender::nodes
@ LIB_ID_CREATE_NO_USER_REFCOUNT
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define ELEM(...)
#define TIP_(msgid)
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:978
#define ID_MISSING(_id)
Definition DNA_ID.h:692
ID_Type
@ ID_LA
@ ID_WO
@ ID_MA
struct NodeMenuSwitch NodeMenuSwitch
struct bNodeSocketValueFloat bNodeSocketValueFloat
struct bNodeSocketValueMenu bNodeSocketValueMenu
struct bNodeSocketValueInt bNodeSocketValueInt
struct NodeRepeatItem NodeRepeatItem
struct NodeCombineBundleItem NodeCombineBundleItem
struct bNodeSocketValueRGBA bNodeSocketValueRGBA
struct bNodeSocketValueVector bNodeSocketValueVector
struct NodeClosureOutput NodeClosureOutput
struct NodeGeometryRepeatInput NodeGeometryRepeatInput
struct NodeEvaluateClosure NodeEvaluateClosure
struct NodeSeparateBundle NodeSeparateBundle
struct NodeGeometryRepeatOutput NodeGeometryRepeatOutput
struct bNodeLink bNodeLink
@ NODE_LINK_VALID
@ SOCK_HIDE_VALUE
struct NodeEvaluateClosureInputItem NodeEvaluateClosureInputItem
struct bNode bNode
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
@ SOCK_MENU
struct bNodeSocketValueBoolean bNodeSocketValueBoolean
struct bNodeTree bNodeTree
struct NodeCombineBundle NodeCombineBundle
struct NodeEnumItem NodeEnumItem
struct NodeClosureOutputItem NodeClosureOutputItem
struct bNodeSocket bNodeSocket
bool is() const
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:620
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
Value & lookup_or_add(const Key &key, const Value &value)
Definition BLI_map.hh:588
void append(const T &value)
static const CPPType & get()
static GVArray from_single(const CPPType &type, int64_t size, const void *value)
KDTree_3d * tree
#define GS(x)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
const bNodeZoneType * zone_type_by_node_type(const int node_type)
bNode * node_add_node(const bContext *C, bNodeTree &ntree, StringRef idname, std::optional< int > unique_identifier=std::nullopt)
Definition node.cc:3477
const DataTypeConversions & get_implicit_type_conversions()
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:3810
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, int flag, std::optional< StringRefNull > dst_unique_name, std::optional< int > dst_unique_identifier, Map< const bNodeSocket *, bNodeSocket * > &new_socket_map, bool allow_duplicate_names=false)
Definition node.cc:3553
int context(const bContext *C, const char *member, bContextDataResult *result)
GreasePencil * from_context(bContext &C)
bool inline_shader_node_tree(const bNodeTree &src_tree, bNodeTree &dst_tree, InlineShaderNodeTreeParams &params)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
static void unique_name(bNode *node)
void * first
NodeClosureOutputItem * items
NodeClosureOutputItems output_items
bNodeSocketRuntimeHandle * runtime
struct bNodeLink * link
bNodeSocketTypeHandle * typeinfo
struct bNodeSocket * next
void * default_value
bNodeTreeTypeHandle * typeinfo
ListBase nodes
ListBase links
ListBase inputs
struct bNode * parent
char name[64]
void * storage
ListBase outputs
int32_t identifier
i
Definition text_draw.cc:230
static bNode * add_node(bNodeTree *ntree, const int type, const blender::float2 loc)