Blender V4.3
NOD_node_declaration.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include <cstdint>
8#include <functional>
9#include <type_traits>
10
11#include "BLI_string_ref.hh"
12#include "BLI_utildefines.h"
13#include "BLI_vector.hh"
14
15#include "BLT_translation.hh"
16
17#include "DNA_node_types.h"
18
19#include "RNA_types.hh"
20
21struct bContext;
22struct bNode;
23struct uiLayout;
24
25namespace blender::nodes {
26
27class NodeDeclarationBuilder;
28
31 None,
36};
37
49
59
60
63class OutputFieldDependency {
64 private:
65 OutputSocketFieldType type_ = OutputSocketFieldType::None;
66 Vector<int> linked_input_indices_;
67
68 public:
69 static OutputFieldDependency ForFieldSource();
70 static OutputFieldDependency ForDataSource();
71 static OutputFieldDependency ForDependentField();
72 static OutputFieldDependency ForPartiallyDependentField(Vector<int> indices);
73
74 OutputSocketFieldType field_type() const;
75 Span<int> linked_input_indices() const;
76
77 BLI_STRUCT_EQUALITY_OPERATORS_2(OutputFieldDependency, type_, linked_input_indices_)
78};
79
89
90namespace anonymous_attribute_lifetime {
91
101
111
121
131
146
147std::ostream &operator<<(std::ostream &stream, const RelationsInNode &relations);
148
149} // namespace anonymous_attribute_lifetime
150namespace aal = anonymous_attribute_lifetime;
151
152using ImplicitInputValueFn = std::function<void(const bNode &node, void *r_value)>;
153
154/* Socket or panel declaration. */
156 public:
157 virtual ~ItemDeclaration() = default;
158};
159
160using ItemDeclarationPtr = std::unique_ptr<ItemDeclaration>;
161
166
171 public:
172 std::string name;
173 std::string short_label;
174 std::string identifier;
175 std::string description;
182 bool hide_label = false;
183 bool hide_value = false;
184 bool compact = false;
185 bool is_multi_input = false;
186 bool no_mute_links = false;
187 bool is_available = true;
188 bool is_attribute_name = false;
192
194 OutputFieldDependency output_field_dependency;
195
196 private:
197 CompositorInputRealizationOptions compositor_realization_options_ =
199
202 int compositor_domain_priority_ = 0;
203
206 bool compositor_expects_single_value_ = false;
207
209 std::function<void(bNode &)> make_available_fn_;
210
211 public:
214 std::unique_ptr<ImplicitInputValueFn> implicit_input_fn;
219 std::unique_ptr<SocketNameRNA> socket_name_rna;
220
223 template<typename SocketDecl> friend class SocketDeclarationBuilder;
224
225 public:
226 virtual ~SocketDeclaration() = default;
227
228 virtual bNodeSocket &build(bNodeTree &ntree, bNode &node) const = 0;
229 virtual bool matches(const bNodeSocket &socket) const = 0;
230 virtual bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const;
231
236 virtual bool can_connect(const bNodeSocket &socket) const = 0;
237
243 void make_available(bNode &node) const;
244
246 int compositor_domain_priority() const;
248
249 protected:
250 void set_common_flags(bNodeSocket &socket) const;
251 bool matches_common_data(const bNodeSocket &socket) const;
252};
253
255
257 protected:
258 /* Index of the socket in the list of inputs or outputs. */
259 int index_ = -1;
261 bool field_on_all_ = false;
265
267
268 public:
269 virtual ~BaseSocketDeclarationBuilder() = default;
270
271 BaseSocketDeclarationBuilder &hide_label(bool value = true);
272
273 BaseSocketDeclarationBuilder &hide_value(bool value = true);
274
275 BaseSocketDeclarationBuilder &multi_input(bool value = true);
276
277 BaseSocketDeclarationBuilder &short_label(std::string value = "");
278
279 BaseSocketDeclarationBuilder &description(std::string value = "");
280
282
284
289 BaseSocketDeclarationBuilder &available(bool value = true);
290
292
294
297
306
309
312
315
318 Span<int> input_indices);
319
322
325
328
334
339
344
347
350
356
362
369 BaseSocketDeclarationBuilder &make_available(std::function<void(bNode &)> fn);
370
376
383 const StructRNA *srna,
384 const void *data,
385 StringRef property_name);
386
388 int index() const;
389
390 bool is_input() const;
391 bool is_output() const;
392};
393
399template<typename SocketDecl>
401 protected:
402 using Self = typename SocketDecl::Builder;
403 static_assert(std::is_base_of_v<SocketDeclaration, SocketDecl>);
404 SocketDecl *decl_;
405
407};
408
409using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>;
410
412
414
419 public:
421 std::string name;
422 std::string description;
424 bool default_collapsed = false;
427
428 private:
431
432 public:
433 virtual ~PanelDeclaration() = default;
434
435 void build(bNodePanelState &panel) const;
436 bool matches(const bNodePanelState &panel) const;
437 void update_or_build(const bNodePanelState &old_panel, bNodePanelState &new_panel) const;
438};
439
441 protected:
449 bool is_complete_ = false;
450
452
453 public:
454 Self &description(std::string value = "");
455 Self &default_closed(bool closed);
457
458 template<typename DeclType>
459 typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
460 template<typename DeclType>
461 typename DeclType::Builder &add_output(StringRef name, StringRef identifier = "");
462
464 StringRef name,
465 StringRef identifier = "");
467 StringRef name,
468 StringRef identifier = "");
470 StringRef name,
471 StringRef identifier = "");
473 StringRef name,
474 StringRef identifier = "");
475
476 void add_separator();
477};
478
479using PanelDeclarationPtr = std::unique_ptr<PanelDeclaration>;
480
482 public:
483 /* Combined list of socket and panel declarations.
484 * This determines order of sockets in the UI and panel content. */
486 /* NOTE: inputs and outputs pointers are owned by the items list. */
489 std::unique_ptr<aal::RelationsInNode> anonymous_attribute_relations_;
490
495
499
503
508
510
512 bool is_valid() const;
513
514 bool matches(const bNode &node) const;
516
521
522 MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration")
523};
524
526 private:
527 NodeDeclaration &declaration_;
528 const bNodeTree *ntree_ = nullptr;
529 const bNode *node_ = nullptr;
531 Vector<BaseSocketDeclarationBuilder *> input_socket_builders_;
532 Vector<BaseSocketDeclarationBuilder *> output_socket_builders_;
534 bool is_function_node_ = false;
535
536 private:
538
539 public:
541 const bNodeTree *ntree = nullptr,
542 const bNode *node = nullptr);
543
544 const bNode *node_or_null() const
545 {
546 declaration_.is_context_dependent = true;
547 return node_;
548 }
549
550 const bNodeTree *tree_or_null() const
551 {
552 declaration_.is_context_dependent = true;
553 return ntree_;
554 }
555
561 {
562 is_function_node_ = true;
563 }
564
565 void finalize();
566
567 void use_custom_socket_order(bool enable = true);
568 void allow_any_socket_order(bool enable = true);
569
570 template<typename DeclType>
571 typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
572 template<typename DeclType>
573 typename DeclType::Builder &add_output(StringRef name, StringRef identifier = "");
574 PanelDeclarationBuilder &add_panel(StringRef name, int identifier = -1);
575
577 StringRef name,
578 StringRef identifier = "");
580 StringRef name,
581 StringRef identifier = "");
583 StringRef name,
584 StringRef identifier = "");
586 StringRef name,
587 StringRef identifier = "");
588
589 void add_separator();
590
592 {
593 if (!declaration_.anonymous_attribute_relations_) {
594 declaration_.anonymous_attribute_relations_ = std::make_unique<aal::RelationsInNode>();
595 }
596 return *declaration_.anonymous_attribute_relations_;
597 }
598
600 {
601 return declaration_;
602 }
603
604 private:
605 template<typename DeclType>
606 typename DeclType::Builder &add_socket(StringRef name,
607 StringRef identifier_in,
608 StringRef identifier_out,
609 eNodeSocketInOut in_out);
610
611 /* Mark the most recent builder as 'complete' when changing builders
612 * so no more items can be added. */
613 void set_active_panel_builder(const PanelDeclarationBuilder *panel_builder);
614
615 void build_remaining_anonymous_attribute_relations();
616};
617
618namespace implicit_field_inputs {
619void position(const bNode &node, void *r_value);
620void normal(const bNode &node, void *r_value);
621void index(const bNode &node, void *r_value);
622void id_or_index(const bNode &node, void *r_value);
623void instance_transform(const bNode &node, void *r_value);
624} // namespace implicit_field_inputs
625
626void build_node_declaration(const bke::bNodeType &typeinfo,
627 NodeDeclaration &r_declaration,
628 const bNodeTree *ntree,
629 const bNode *node);
630
631std::unique_ptr<SocketDeclaration> make_declaration_for_socket_type(
632 eNodeSocketDatatype socket_type);
633
634/* -------------------------------------------------------------------- */
638template<typename DeclType>
639typename DeclType::Builder &PanelDeclarationBuilder::add_input(StringRef name,
640 StringRef identifier)
641{
642 if (is_complete_) {
643 static typename DeclType::Builder dummy_builder = {};
645 return dummy_builder;
646 }
647 ++this->decl_->num_child_decls;
648 return node_decl_builder_->add_socket<DeclType>(name, identifier, "", SOCK_IN);
649}
650
651template<typename DeclType>
652typename DeclType::Builder &PanelDeclarationBuilder::add_output(StringRef name,
653 StringRef identifier)
654{
655 if (is_complete_) {
656 static typename DeclType::Builder dummy_builder = {};
658 return dummy_builder;
659 }
660 ++this->decl_->num_child_decls;
661 return node_decl_builder_->add_socket<DeclType>(name, "", identifier, SOCK_OUT);
662}
663
666/* -------------------------------------------------------------------- */
671{
672 return index_;
673}
674
676{
677 return decl_base_->in_out == SOCK_IN;
678}
679
681{
682 return decl_base_->in_out == SOCK_OUT;
683}
684
687/* -------------------------------------------------------------------- */
691template<typename DeclType>
692inline typename DeclType::Builder &NodeDeclarationBuilder::add_input(StringRef name,
693 StringRef identifier)
694{
695 set_active_panel_builder(nullptr);
696 return this->add_socket<DeclType>(name, identifier, "", SOCK_IN);
697}
698
699template<typename DeclType>
700inline typename DeclType::Builder &NodeDeclarationBuilder::add_output(StringRef name,
701 StringRef identifier)
702{
703 set_active_panel_builder(nullptr);
704 return this->add_socket<DeclType>(name, "", identifier, SOCK_OUT);
705}
706
707template<typename DeclType>
708inline typename DeclType::Builder &NodeDeclarationBuilder::add_socket(StringRef name,
709 StringRef identifier_in,
710 StringRef identifier_out,
711 eNodeSocketInOut in_out)
712{
713 static_assert(std::is_base_of_v<SocketDeclaration, DeclType>);
714 using Builder = typename DeclType::Builder;
715
716 BLI_assert(ELEM(in_out, SOCK_IN, SOCK_OUT));
717
718 std::unique_ptr<Builder> socket_decl_builder = std::make_unique<Builder>();
719 socket_decl_builder->node_decl_builder_ = this;
720
721 if (in_out & SOCK_IN) {
722 std::unique_ptr<DeclType> socket_decl = std::make_unique<DeclType>();
723 socket_decl_builder->decl_ = &*socket_decl;
724 socket_decl_builder->decl_base_ = &*socket_decl;
725 socket_decl->name = name;
726 socket_decl->identifier = identifier_in.is_empty() ? name : identifier_in;
727 socket_decl->in_out = SOCK_IN;
728 socket_decl->socket_type = DeclType::static_socket_type;
729 socket_decl_builder->index_ = declaration_.inputs.append_and_get_index(socket_decl.get());
730 declaration_.items.append(std::move(socket_decl));
731 input_socket_builders_.append(&*socket_decl_builder);
732 }
733 if (in_out & SOCK_OUT) {
734 std::unique_ptr<DeclType> socket_decl = std::make_unique<DeclType>();
735 socket_decl_builder->decl_ = &*socket_decl;
736 socket_decl_builder->decl_base_ = &*socket_decl;
737 socket_decl->name = name;
738 socket_decl->identifier = identifier_out.is_empty() ? name : identifier_out;
739 socket_decl->in_out = SOCK_OUT;
740 socket_decl->socket_type = DeclType::static_socket_type;
741 socket_decl_builder->index_ = declaration_.outputs.append_and_get_index(socket_decl.get());
742 declaration_.items.append(std::move(socket_decl));
743 output_socket_builders_.append(&*socket_decl_builder);
744 }
745
746 if (is_function_node_) {
747 if (in_out == SOCK_IN) {
748 socket_decl_builder->supports_field();
749 }
750 else {
751 socket_decl_builder->dependent_field();
752 }
753 }
754
755 Builder &socket_decl_builder_ref = *socket_decl_builder;
756 socket_builders_.append(std::move(socket_decl_builder));
757
758 return socket_decl_builder_ref;
759}
760
763} // namespace blender::nodes
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_STRUCT_EQUALITY_OPERATORS_5(Type, m1, m2, m3, m4, m5)
#define BLI_STRUCT_EQUALITY_OPERATORS_2(Type, m1, m2)
#define ENUM_OPERATORS(_type, _max)
#define ELEM(...)
#define BLT_I18NCONTEXT_DEFAULT
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
eNodeSocketDatatype
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
constexpr bool is_empty() const
void append(const T &value)
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()
virtual ~ItemDeclaration()=default
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="")
std::unique_ptr< aal::RelationsInNode > anonymous_attribute_relations_
Vector< ItemDeclarationPtr > items
Vector< SocketDeclaration * > inputs
bool matches(const bNode &node) const
const aal::RelationsInNode * anonymous_attribute_relations() 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="")
virtual ~PanelDeclaration()=default
void update_or_build(const bNodePanelState &old_panel, bNodePanelState &new_panel) const
bool matches(const bNodePanelState &panel) const
void build(bNodePanelState &panel) const
virtual bool matches(const bNodeSocket &socket) const =0
std::unique_ptr< SocketNameRNA > socket_name_rna
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 ~SocketDeclaration()=default
virtual bool can_connect(const bNodeSocket &socket) const =0
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
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
std::unique_ptr< SocketDeclaration > SocketDeclarationPtr
void build_node_declaration(const bke::bNodeType &typeinfo, NodeDeclaration &r_declaration, const bNodeTree *ntree, const bNode *node)
std::unique_ptr< ItemDeclaration > ItemDeclarationPtr
std::unique_ptr< SocketDeclaration > make_declaration_for_socket_type(const eNodeSocketDatatype socket_type)
std::unique_ptr< PanelDeclaration > PanelDeclarationPtr
std::function< void(const bNode &node, void *r_value)> ImplicitInputValueFn
unsigned char uint8_t
Definition stdint.h:78
Definition DNA_ID.h:413
PointerRNA * ptr
Definition wm_files.cc:4126