Blender V4.3
node_declaration.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
8
9#include "BLI_stack.hh"
10#include "BLI_utildefines.h"
11
13#include "BKE_node.hh"
14#include "BKE_node_runtime.hh"
16
17#include "RNA_access.hh"
18
19namespace blender::nodes {
20
21static void reset_declaration(NodeDeclaration &declaration)
22{
23 std::destroy_at(&declaration);
24 new (&declaration) NodeDeclaration();
25}
26
28 NodeDeclaration &r_declaration,
29 const bNodeTree *ntree,
30 const bNode *node)
31{
32 reset_declaration(r_declaration);
33 NodeDeclarationBuilder node_decl_builder{r_declaration, ntree, node};
34 typeinfo.declare(node_decl_builder);
35 node_decl_builder.finalize();
36}
37
38void NodeDeclarationBuilder::build_remaining_anonymous_attribute_relations()
39{
40 Vector<int> geometry_inputs;
41 for (const int i : declaration_.inputs.index_range()) {
42 if (dynamic_cast<decl::Geometry *>(declaration_.inputs[i])) {
43 geometry_inputs.append(i);
44 }
45 }
46 Vector<int> geometry_outputs;
47 for (const int i : declaration_.outputs.index_range()) {
48 if (dynamic_cast<decl::Geometry *>(declaration_.outputs[i])) {
49 geometry_outputs.append(i);
50 }
51 }
52
53 for (BaseSocketDeclarationBuilder *socket_builder : input_socket_builders_) {
54 if (socket_builder->field_on_all_) {
55 aal::RelationsInNode &relations = this->get_anonymous_attribute_relations();
56 const int field_input = socket_builder->index_;
57 for (const int geometry_input : geometry_inputs) {
58 relations.eval_relations.append({field_input, geometry_input});
59 }
60 }
61 }
62 for (BaseSocketDeclarationBuilder *socket_builder : output_socket_builders_) {
63 if (socket_builder->field_on_all_) {
64 aal::RelationsInNode &relations = this->get_anonymous_attribute_relations();
65 const int field_output = socket_builder->index_;
66 for (const int geometry_output : geometry_outputs) {
67 relations.available_relations.append({field_output, geometry_output});
68 }
69 }
70 if (socket_builder->reference_pass_all_) {
71 aal::RelationsInNode &relations = this->get_anonymous_attribute_relations();
72 const int field_output = socket_builder->index_;
73 for (const int input_i : declaration_.inputs.index_range()) {
74 SocketDeclaration &input_socket_decl = *declaration_.inputs[input_i];
75 if (input_socket_decl.input_field_type != InputSocketFieldType::None) {
76 relations.reference_relations.append({input_i, field_output});
77 }
78 }
79 }
80 if (socket_builder->propagate_from_all_) {
81 aal::RelationsInNode &relations = this->get_anonymous_attribute_relations();
82 const int geometry_output = socket_builder->index_;
83 for (const int geometry_input : geometry_inputs) {
84 relations.propagate_relations.append({geometry_input, geometry_output});
85 }
86 }
87 }
88}
89
91{
92 this->build_remaining_anonymous_attribute_relations();
93 BLI_assert(declaration_.is_valid());
94}
95
97 const bNodeTree *ntree,
98 const bNode *node)
99 : declaration_(declaration), ntree_(ntree), node_(node)
100{
101}
102
104{
105 declaration_.use_custom_socket_order = enable;
106}
107
109{
111 declaration_.allow_any_socket_order = enable;
112}
113
115{
116 if (in_out == SOCK_IN) {
117 return inputs;
118 }
119 return outputs;
120}
121
122void NodeDeclarationBuilder::set_active_panel_builder(const PanelDeclarationBuilder *panel_builder)
123{
124 if (panel_builders_.is_empty()) {
125 BLI_assert(panel_builder == nullptr);
126 return;
127 }
128
129 BLI_assert(!panel_builder || !panel_builder->is_complete_);
130 PanelDeclarationBuilder *last_panel_builder = panel_builders_.last().get();
131 if (last_panel_builder != panel_builder) {
132 last_panel_builder->is_complete_ = true;
133 }
134}
135
136namespace anonymous_attribute_lifetime {
137
138std::ostream &operator<<(std::ostream &stream, const RelationsInNode &relations)
139{
140 stream << "Propagate Relations: " << relations.propagate_relations.size() << "\n";
141 for (const PropagateRelation &relation : relations.propagate_relations) {
142 stream << " " << relation.from_geometry_input << " -> " << relation.to_geometry_output
143 << "\n";
144 }
145 stream << "Reference Relations: " << relations.reference_relations.size() << "\n";
146 for (const ReferenceRelation &relation : relations.reference_relations) {
147 stream << " " << relation.from_field_input << " -> " << relation.to_field_output << "\n";
148 }
149 stream << "Eval Relations: " << relations.eval_relations.size() << "\n";
150 for (const EvalRelation &relation : relations.eval_relations) {
151 stream << " eval " << relation.field_input << " on " << relation.geometry_input << "\n";
152 }
153 stream << "Available Relations: " << relations.available_relations.size() << "\n";
154 for (const AvailableRelation &relation : relations.available_relations) {
155 stream << " " << relation.field_output << " available on " << relation.geometry_output
156 << "\n";
157 }
158 stream << "Available on None: " << relations.available_on_none.size() << "\n";
159 for (const int i : relations.available_on_none) {
160 stream << " output " << i << " available on none\n";
161 }
162 return stream;
163}
164
165} // namespace anonymous_attribute_lifetime
166
168{
169 if (!this->use_custom_socket_order) {
170 /* Skip validation for conventional socket layouts. */
171 return true;
172 }
173
174 /* Validation state for the interface root items as well as any panel content. */
175 struct ValidationState {
176 /* Remaining number of items expected in a panel */
177 int remaining_items = 0;
178 /* Sockets first, followed by panels. */
180 /* Output sockets first, followed by input sockets. */
181 eNodeSocketInOut socket_in_out = SOCK_OUT;
182 };
183
184 Stack<ValidationState> panel_states;
185 panel_states.push({});
186
187 for (const ItemDeclarationPtr &item_decl : items) {
188 BLI_assert(panel_states.size() >= 1);
189 ValidationState &state = panel_states.peek();
190
191 if (const SocketDeclaration *socket_decl = dynamic_cast<const SocketDeclaration *>(
192 item_decl.get()))
193 {
194 if (state.item_type != NODE_INTERFACE_SOCKET && !this->allow_any_socket_order) {
195 std::cout << "Socket added after panel" << std::endl;
196 return false;
197 }
198
199 /* Check for consistent outputs.., inputs.. blocks. */
200 if (state.socket_in_out == SOCK_OUT && socket_decl->in_out == SOCK_IN) {
201 /* Start of input sockets. */
202 state.socket_in_out = SOCK_IN;
203 }
204 if (socket_decl->in_out != state.socket_in_out && !this->allow_any_socket_order) {
205 std::cout << "Output socket added after input socket" << std::endl;
206 return false;
207 }
208
209 /* Item counting for the panels, but ignore for root items. */
210 if (panel_states.size() > 1) {
211 if (state.remaining_items <= 0) {
212 std::cout << "More sockets than expected in panel" << std::endl;
213 return false;
214 }
215 --state.remaining_items;
216 /* Panel closed after last item is added. */
217 if (state.remaining_items == 0) {
218 panel_states.pop();
219 }
220 }
221 }
222 else if (const PanelDeclaration *panel_decl = dynamic_cast<const PanelDeclaration *>(
223 item_decl.get()))
224 {
225 if (state.item_type == NODE_INTERFACE_SOCKET) {
226 /* Start of panels section */
227 state.item_type = NODE_INTERFACE_PANEL;
228 }
230
231 if (panel_decl->num_child_decls > 0) {
232 /* New panel started. */
233 panel_states.push({panel_decl->num_child_decls});
234 }
235 }
236 else if (dynamic_cast<const SeparatorDeclaration *>(item_decl.get())) {
237 if (panel_states.size() > 1) {
238 --state.remaining_items;
239 if (state.remaining_items == 0) {
240 panel_states.pop();
241 }
242 }
243 }
244 else {
246 return false;
247 }
248 }
249
250 /* All panels complete? */
251 if (panel_states.size() != 1) {
252 std::cout << "Incomplete last panel" << std::endl;
253 return false;
254 }
255 return true;
256}
257
258bool NodeDeclaration::matches(const bNode &node) const
259{
260 const bNodeSocket *current_input = static_cast<bNodeSocket *>(node.inputs.first);
261 const bNodeSocket *current_output = static_cast<bNodeSocket *>(node.outputs.first);
262 const bNodePanelState *current_panel = node.panel_states_array;
263 for (const ItemDeclarationPtr &item_decl : items) {
264 if (const SocketDeclaration *socket_decl = dynamic_cast<const SocketDeclaration *>(
265 item_decl.get()))
266 {
267 switch (socket_decl->in_out) {
268 case SOCK_IN:
269 if (current_input == nullptr || !socket_decl->matches(*current_input)) {
270 return false;
271 }
272 current_input = current_input->next;
273 break;
274 case SOCK_OUT:
275 if (current_output == nullptr || !socket_decl->matches(*current_output)) {
276 return false;
277 }
278 current_output = current_output->next;
279 break;
280 }
281 }
282 else if (const PanelDeclaration *panel_decl = dynamic_cast<const PanelDeclaration *>(
283 item_decl.get()))
284 {
285 if (!node.panel_states().contains_ptr(current_panel) || !panel_decl->matches(*current_panel))
286 {
287 return false;
288 }
289 ++current_panel;
290 }
291 else if (dynamic_cast<const SeparatorDeclaration *>(item_decl.get())) {
292 /* Separators are ignored here because they don't have corresponding data in DNA. */
293 }
294 else {
295 /* Unknown item type. */
297 }
298 }
299 /* If items are left over, some were removed from the declaration. */
300 if (current_input != nullptr || current_output != nullptr ||
301 node.panel_states().contains_ptr(current_panel))
302 {
303 return false;
304 }
305 return true;
306}
307
309 bNode &node,
310 bNodeSocket &socket) const
311{
312 /* By default just rebuild. */
313 BLI_assert(socket.in_out == this->in_out);
314 UNUSED_VARS_NDEBUG(socket);
315 return this->build(ntree, node);
316}
317
327
329{
330 if (socket.name != this->name) {
331 return false;
332 }
333 if (socket.identifier != this->identifier) {
334 return false;
335 }
336 if (((socket.flag & SOCK_COMPACT) != 0) != this->compact) {
337 return false;
338 }
339 if (((socket.flag & SOCK_HIDE_VALUE) != 0) != this->hide_value) {
340 return false;
341 }
342 if (((socket.flag & SOCK_HIDE_LABEL) != 0) != this->hide_label) {
343 return false;
344 }
345 if (((socket.flag & SOCK_MULTI_INPUT) != 0) != this->is_multi_input) {
346 return false;
347 }
348 if (((socket.flag & SOCK_NO_INTERNAL_LINK) != 0) != this->no_mute_links) {
349 return false;
350 }
351 if (((socket.flag & SOCK_UNAVAIL) != 0) != !this->is_available) {
352 return false;
353 }
354 return true;
355}
356
358{
359 std::unique_ptr<PanelDeclaration> panel_decl = std::make_unique<PanelDeclaration>();
360 std::unique_ptr<PanelDeclarationBuilder> panel_decl_builder =
361 std::make_unique<PanelDeclarationBuilder>();
362 panel_decl_builder->decl_ = &*panel_decl;
363
364 panel_decl_builder->node_decl_builder_ = this;
365 if (identifier >= 0) {
366 panel_decl->identifier = identifier;
367 }
368 else {
369 /* Use index as identifier. */
370 panel_decl->identifier = declaration_.items.size();
371 }
372 panel_decl->name = name;
373 declaration_.items.append(std::move(panel_decl));
374
375 PanelDeclarationBuilder &builder_ref = *panel_decl_builder;
376 panel_builders_.append(std::move(panel_decl_builder));
377 set_active_panel_builder(&builder_ref);
378
379 return builder_ref;
380}
381
383{
384 panel = {0};
385 panel.identifier = this->identifier;
386 SET_FLAG_FROM_TEST(panel.flag, this->default_collapsed, NODE_PANEL_COLLAPSED);
387}
388
390{
391 return panel.identifier == this->identifier;
392}
393
395 bNodePanelState &new_panel) const
396{
397 build(new_panel);
398 /* Copy existing state to the new panel */
399 SET_FLAG_FROM_TEST(new_panel.flag, old_panel.is_collapsed(), NODE_PANEL_COLLAPSED);
400}
401
402template<typename Fn>
403static bool socket_type_to_static_decl_type(const eNodeSocketDatatype socket_type, Fn &&fn)
404{
405 switch (socket_type) {
406 case SOCK_FLOAT:
408 return true;
409 case SOCK_VECTOR:
411 return true;
412 case SOCK_RGBA:
414 return true;
415 case SOCK_BOOLEAN:
417 return true;
418 case SOCK_ROTATION:
420 return true;
421 case SOCK_MATRIX:
423 return true;
424 case SOCK_INT:
425 fn(TypeTag<decl::Int>());
426 return true;
427 case SOCK_STRING:
429 return true;
430 case SOCK_GEOMETRY:
432 return true;
433 case SOCK_OBJECT:
435 return true;
436 case SOCK_IMAGE:
438 return true;
439 case SOCK_COLLECTION:
441 return true;
442 case SOCK_MATERIAL:
444 return true;
445 case SOCK_MENU:
447 return true;
448 default:
449 return false;
450 }
451}
452
453std::unique_ptr<SocketDeclaration> make_declaration_for_socket_type(
454 const eNodeSocketDatatype socket_type)
455{
456 std::unique_ptr<SocketDeclaration> decl;
457 socket_type_to_static_decl_type(socket_type, [&](auto type_tag) {
458 using DeclT = typename decltype(type_tag)::type;
459 decl = std::make_unique<DeclT>();
460 });
461 return decl;
462}
463
465 const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier)
466{
467 BaseSocketDeclarationBuilder *decl = nullptr;
468 socket_type_to_static_decl_type(socket_type, [&](auto type_tag) {
469 using DeclT = typename decltype(type_tag)::type;
470 decl = &this->add_input<DeclT>(name, identifier);
471 });
472 if (!decl) {
474 decl = &this->add_input<decl::Float>("", "");
475 }
476 return *decl;
477}
478
480 const StringRef name,
481 const StringRef identifier)
482{
483 return this->add_input(*bke::custom_data_type_to_socket_type(data_type), name, identifier);
484}
485
487 const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier)
488{
489 BaseSocketDeclarationBuilder *decl = nullptr;
490 socket_type_to_static_decl_type(socket_type, [&](auto type_tag) {
491 using DeclT = typename decltype(type_tag)::type;
492 decl = &this->add_output<DeclT>(name, identifier);
493 });
494 if (!decl) {
496 decl = &this->add_output<decl::Float>("", "");
497 }
498 return *decl;
499}
500
502 const StringRef name,
503 const StringRef identifier)
504{
505 return this->add_output(*bke::custom_data_type_to_socket_type(data_type), name, identifier);
506}
507
509{
510 declaration_.items.append(std::make_unique<SeparatorDeclaration>());
511}
512
514 const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier)
515{
516 BaseSocketDeclarationBuilder *decl = nullptr;
517 socket_type_to_static_decl_type(socket_type, [&](auto type_tag) {
518 using DeclT = typename decltype(type_tag)::type;
519 decl = &this->add_input<DeclT>(name, identifier);
520 });
521 if (!decl) {
523 decl = &this->add_input<decl::Float>("", "");
524 }
525 return *decl;
526}
527
529 const StringRef name,
530 const StringRef identifier)
531{
532 return this->add_input(*bke::custom_data_type_to_socket_type(data_type), name, identifier);
533}
534
536 const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier)
537{
538 BaseSocketDeclarationBuilder *decl = nullptr;
539 socket_type_to_static_decl_type(socket_type, [&](auto type_tag) {
540 using DeclT = typename decltype(type_tag)::type;
541 decl = &this->add_output<DeclT>(name, identifier);
542 });
543 if (!decl) {
545 decl = &this->add_output<decl::Float>("", "");
546 }
547 return *decl;
548}
549
551 const StringRef name,
552 const StringRef identifier)
553{
554 return this->add_output(*bke::custom_data_type_to_socket_type(data_type), name, identifier);
555}
556
565
572
574 Vector<int> input_dependencies)
575{
576 BLI_assert(this->is_output());
577 this->reference_pass(input_dependencies);
578 decl_base_->output_field_dependency = OutputFieldDependency::ForPartiallyDependentField(
579 std::move(input_dependencies));
580 return *this;
581}
582
588
594
601
603 const Span<int> input_indices)
604{
605 BLI_assert(this->is_output());
607 for (const int from_input : input_indices) {
608 aal::ReferenceRelation relation;
609 relation.from_field_input = from_input;
610 relation.to_field_output = index_;
611 relations.reference_relations.append(relation);
612 }
613 return *this;
614}
615
617{
619 if (this->is_input()) {
620 this->supports_field();
621 for (const int input_index : indices) {
622 aal::EvalRelation relation;
623 relation.field_input = index_;
624 relation.geometry_input = input_index;
625 relations.eval_relations.append(relation);
626 }
627 }
628 else {
629 this->field_source();
630 for (const int output_index : indices) {
631 aal::AvailableRelation relation;
632 relation.field_output = index_;
633 relation.geometry_output = output_index;
634 relations.available_relations.append(relation);
635 }
636 }
637 return *this;
638}
639
641{
642 decl_base_->short_label = std::move(value);
643 return *this;
644}
645
647{
648 decl_base_->description = std::move(value);
649 return *this;
650}
651
653{
654 decl_base_->translation_context = std::move(value);
655 return *this;
656}
657
663
669
675
681
683{
684 if (this->is_input()) {
685 this->supports_field();
686 }
687 if (this->is_output()) {
688 this->field_source();
689 }
690 field_on_all_ = true;
691 return *this;
692}
693
695{
696 BLI_assert(this->is_output());
697 decl_base_->output_field_dependency = OutputFieldDependency::ForFieldSource();
698 return *this;
699}
700
702{
703 BLI_assert(this->is_input());
704 this->hide_value();
706 decl_base_->implicit_input_fn = std::make_unique<ImplicitInputValueFn>(std::move(fn));
707 return *this;
708}
709
717
719 ImplicitInputValueFn fn, const Span<int> input_indices)
720{
721 this->field_on(input_indices);
722 this->implicit_field(fn);
723 return *this;
724}
725
727{
728 BLI_assert(this->is_output());
729 decl_base_->output_field_dependency = OutputFieldDependency::ForDependentField();
730 this->reference_pass_all();
731 return *this;
732}
733
740
746
752
755{
756 decl_base_->compositor_realization_options_ = value;
757 return *this;
758}
759
761 int priority)
762{
763 decl_base_->compositor_domain_priority_ = priority;
764 return *this;
765}
766
768 bool value)
769{
770 decl_base_->compositor_expects_single_value_ = value;
771 return *this;
772}
773
775 std::function<void(bNode &)> fn)
776{
777 decl_base_->make_available_fn_ = std::move(fn);
778 return *this;
779}
780
786
787BaseSocketDeclarationBuilder &BaseSocketDeclarationBuilder ::socket_name_ptr(
788 const PointerRNA ptr, const StringRef property_name)
789{
790 decl_base_->socket_name_rna = std::make_unique<SocketNameRNA>();
791 decl_base_->socket_name_rna->owner = ptr;
792 decl_base_->socket_name_rna->property_name = property_name;
793 return *this;
794}
795
797 const ID *id, const StructRNA *srna, const void *data, StringRef property_name)
798{
799 /* Doing const-casts here because this data is generally only available as const when creating
800 * the declaration, but it's still valid to modify later. */
801 return this->socket_name_ptr(RNA_pointer_create(const_cast<ID *>(id),
802 const_cast<StructRNA *>(srna),
803 const_cast<void *>(data)),
804 property_name);
805}
806
807OutputFieldDependency OutputFieldDependency::ForFieldSource()
808{
809 OutputFieldDependency field_dependency;
810 field_dependency.type_ = OutputSocketFieldType::FieldSource;
811 return field_dependency;
812}
813
814OutputFieldDependency OutputFieldDependency::ForDataSource()
815{
816 OutputFieldDependency field_dependency;
817 field_dependency.type_ = OutputSocketFieldType::None;
818 return field_dependency;
819}
820
821OutputFieldDependency OutputFieldDependency::ForDependentField()
822{
823 OutputFieldDependency field_dependency;
824 field_dependency.type_ = OutputSocketFieldType::DependentField;
825 return field_dependency;
826}
827
828OutputFieldDependency OutputFieldDependency::ForPartiallyDependentField(Vector<int> indices)
829{
830 OutputFieldDependency field_dependency;
831 if (indices.is_empty()) {
832 field_dependency.type_ = OutputSocketFieldType::None;
833 }
834 else {
835 field_dependency.type_ = OutputSocketFieldType::PartiallyDependent;
836 field_dependency.linked_input_indices_ = std::move(indices);
837 }
838 return field_dependency;
839}
840
841OutputSocketFieldType OutputFieldDependency::field_type() const
842{
843 return type_;
844}
845
846Span<int> OutputFieldDependency::linked_input_indices() const
847{
848 return linked_input_indices_;
849}
850
852{
853 return compositor_realization_options_;
854}
855
857{
858 return compositor_domain_priority_;
859}
860
862{
863 return compositor_expects_single_value_;
864}
865
867{
868 if (make_available_fn_) {
869 make_available_fn_(node);
870 }
871}
872
874{
875 decl_->description = std::move(value);
876 return *this;
877}
878
880{
881 decl_->default_collapsed = closed;
882 return *this;
883}
884
890
891namespace implicit_field_inputs {
892
893void position(const bNode & /*node*/, void *r_value)
894{
896}
897
898void normal(const bNode & /*node*/, void *r_value)
899{
900 new (r_value)
901 bke::SocketValueVariant(fn::Field<float3>(std::make_shared<bke::NormalFieldInput>()));
902}
903
904void index(const bNode & /*node*/, void *r_value)
905{
906 new (r_value) bke::SocketValueVariant(fn::Field<int>(std::make_shared<fn::IndexFieldInput>()));
907}
908
909void id_or_index(const bNode & /*node*/, void *r_value)
910{
911 new (r_value)
912 bke::SocketValueVariant(fn::Field<int>(std::make_shared<bke::IDAttributeFieldInput>()));
913}
914
915void instance_transform(const bNode & /*node*/, void *r_value)
916{
917 new (r_value)
919}
920
921} // namespace implicit_field_inputs
922
923} // namespace blender::nodes
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define UNUSED_VARS_NDEBUG(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
@ SOCK_HIDE_LABEL
@ SOCK_HIDE_VALUE
@ SOCK_MULTI_INPUT
@ SOCK_COMPACT
@ SOCK_UNAVAIL
@ SOCK_NO_INTERNAL_LINK
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
@ NODE_PANEL_COLLAPSED
void push(const T &value)
Definition BLI_stack.hh:213
int64_t size() const
Definition BLI_stack.hh:316
int64_t size() const
void append(const T &value)
static fn::GField Create(std::string name, const CPPType &type, std::optional< std::string > socket_inspection_name=std::nullopt)
BaseSocketDeclarationBuilder & dependent_field()
BaseSocketDeclarationBuilder & align_with_previous(bool value=true)
BaseSocketDeclarationBuilder & implicit_field_on_all(ImplicitInputValueFn fn)
BaseSocketDeclarationBuilder & make_available(std::function< void(bNode &)> fn)
BaseSocketDeclarationBuilder & field_source()
BaseSocketDeclarationBuilder & implicit_field_on(ImplicitInputValueFn fn, Span< int > input_indices)
BaseSocketDeclarationBuilder & propagate_all()
BaseSocketDeclarationBuilder & available(bool value=true)
BaseSocketDeclarationBuilder & field_on_all()
BaseSocketDeclarationBuilder & is_attribute_name(bool value=true)
BaseSocketDeclarationBuilder & reference_pass(Span< int > input_indices)
BaseSocketDeclarationBuilder & compositor_realization_options(CompositorInputRealizationOptions value)
BaseSocketDeclarationBuilder & description(std::string value="")
BaseSocketDeclarationBuilder & socket_name_ptr(PointerRNA ptr, StringRef property_name)
BaseSocketDeclarationBuilder & compositor_expects_single_value(bool value=true)
BaseSocketDeclarationBuilder & short_label(std::string value="")
BaseSocketDeclarationBuilder & supports_field()
BaseSocketDeclarationBuilder & hide_label(bool value=true)
BaseSocketDeclarationBuilder & translation_context(std::string value=BLT_I18NCONTEXT_DEFAULT)
BaseSocketDeclarationBuilder & implicit_field(ImplicitInputValueFn fn)
BaseSocketDeclarationBuilder & multi_input(bool value=true)
BaseSocketDeclarationBuilder & is_default_link_socket(bool value=true)
BaseSocketDeclarationBuilder & compositor_domain_priority(int priority)
BaseSocketDeclarationBuilder & field_source_reference_all()
BaseSocketDeclarationBuilder & field_on(Span< int > indices)
BaseSocketDeclarationBuilder & hide_value(bool value=true)
BaseSocketDeclarationBuilder & no_muted_links(bool value=true)
BaseSocketDeclarationBuilder & reference_pass_all()
aal::RelationsInNode & get_anonymous_attribute_relations()
NodeDeclarationBuilder(NodeDeclaration &declaration, const bNodeTree *ntree=nullptr, const bNode *node=nullptr)
DeclType::Builder & add_input(StringRef name, StringRef identifier="")
PanelDeclarationBuilder & add_panel(StringRef name, int identifier=-1)
DeclType::Builder & add_output(StringRef name, StringRef identifier="")
Vector< ItemDeclarationPtr > items
Vector< SocketDeclaration * > inputs
bool matches(const bNode &node) const
Vector< SocketDeclaration * > outputs
Span< SocketDeclaration * > sockets(eNodeSocketInOut in_out) const
Self & description(std::string value="")
DeclType::Builder & add_input(StringRef name, StringRef identifier="")
Self & draw_buttons(PanelDrawButtonsFunction func)
DeclType::Builder & add_output(StringRef name, StringRef identifier="")
void update_or_build(const bNodePanelState &old_panel, bNodePanelState &new_panel) const
bool matches(const bNodePanelState &panel) const
void build(bNodePanelState &panel) const
bool matches_common_data(const bNodeSocket &socket) const
std::unique_ptr< ImplicitInputValueFn > implicit_input_fn
void make_available(bNode &node) const
const CompositorInputRealizationOptions & compositor_realization_options() const
virtual bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
void set_common_flags(bNodeSocket &socket) const
virtual bNodeSocket & build(bNodeTree &ntree, bNode &node) const =0
static ushort indices[]
static ulong state[N]
std::optional< eNodeSocketDatatype > custom_data_type_to_socket_type(eCustomDataType type)
Definition node.cc:4403
std::ostream & operator<<(std::ostream &stream, const RelationsInNode &relations)
void id_or_index(const bNode &, void *r_value)
void index(const bNode &, void *r_value)
void position(const bNode &, void *r_value)
void instance_transform(const bNode &, void *r_value)
void normal(const bNode &, void *r_value)
void(*)(uiLayout *, bContext *, PointerRNA *) PanelDrawButtonsFunction
void build_node_declaration(const bke::bNodeType &typeinfo, NodeDeclaration &r_declaration, const bNodeTree *ntree, const bNode *node)
static bool socket_type_to_static_decl_type(const eNodeSocketDatatype socket_type, Fn &&fn)
std::unique_ptr< ItemDeclaration > ItemDeclarationPtr
static void reset_declaration(NodeDeclaration &declaration)
std::unique_ptr< SocketDeclaration > make_declaration_for_socket_type(const eNodeSocketDatatype socket_type)
std::function< void(const bNode &node, void *r_value)> ImplicitInputValueFn
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
Definition DNA_ID.h:413
struct bNodeSocket * next
char identifier[64]
Defines a node type.
Definition BKE_node.hh:218
NodeDeclareFunction declare
Definition BKE_node.hh:347
PointerRNA * ptr
Definition wm_files.cc:4126