28 : context_(context), exec_system_(system), current_node_(nullptr), active_viewer_(nullptr)
42 node->convert_to_operations(converter, *context_);
45 current_node_ =
nullptr;
53 inverse_input_map.
add(item.value, item.key);
63 if (!op_from || op_to_list.
is_empty()) {
84 save_graphviz(
"compositor_prior_folding");
90 save_graphviz(
"compositor_prior_merging");
91 merge_equal_operations();
108 operation->
set_id(operations_.size());
109 operations_.append(operation);
121 unlink_inputs_and_relink_outputs(operation, constant_operation);
125void NodeOperationBuilder::unlink_inputs_and_relink_outputs(
NodeOperation *unlinked_op,
129 while (i < links_.size()) {
130 Link &link = links_[i];
131 if (&link.to()->get_operation() == unlinked_op) {
132 link.to()->set_link(
nullptr);
137 if (&link.from()->get_operation() == unlinked_op) {
155 input_map_.add_new(operation_socket, node_socket);
164 output_map_.add_new(node_socket, operation_socket);
169 if (to->is_connected()) {
173 links_.append(
Link(from, to));
182 for (
Link &link : links_) {
183 if (link.to() == to) {
185 to->set_link(
nullptr);
187 links_.remove(index);
213 PreviewOperation *operation =
new PreviewOperation(
214 &scene->view_settings,
215 &scene->display_settings,
248 if (!active_viewer_) {
249 active_viewer_ = viewer;
260 active_viewer_ = viewer;
272 for (
const Link &link : links_) {
282 if (link.from()->get_data_type() != link.to()->get_data_type()) {
283 convert_links.
append(link);
286 for (
const Link &link : convert_links) {
305 for (
int k = 0; k < op->get_number_of_input_sockets(); ++k) {
307 if (!input->is_connected()) {
308 pending_inputs.
append(input);
320 switch (input->get_data_type()) {
376 for (
const Link &link : links_) {
378 if (link.from()->get_operation().get_flags().is_proxy_operation &&
379 !link.to()->get_operation().get_flags().is_proxy_operation)
385 for (
const Link &link : proxy_links) {
390 from = from->get_operation().get_input_socket(0)->get_link();
391 }
while (from && from->get_operation().get_flags().is_proxy_operation);
408 if (op->is_output_operation(context_->
is_rendering()) && !op->get_flags().is_preview_operation)
411 op->determine_canvas(preferred_area, canvas);
412 op->set_canvas(canvas);
417 if (op->is_output_operation(context_->
is_rendering()) && op->get_flags().is_preview_operation)
420 op->determine_canvas(preferred_area, canvas);
421 op->set_canvas(canvas);
428 for (
const Link &link : links_) {
430 const rcti &from_canvas = link.from()->get_operation().get_canvas();
431 const rcti &to_canvas = link.to()->get_operation().get_canvas();
433 bool needs_conversion;
435 needs_conversion = from_canvas.
xmin != to_canvas.
xmin ||
442 if (needs_conversion) {
443 convert_links.
append(link);
447 for (
const Link &link : convert_links) {
457 std::optional<NodeOperationHash>
hash = op->generate_hash();
465void NodeOperationBuilder::merge_equal_operations()
467 bool check_for_next_merge =
true;
468 while (check_for_next_merge) {
473 std::sort(hashes.
begin(), hashes.
end());
475 bool any_merged =
false;
476 const NodeOperationHash *prev_hash =
nullptr;
477 for (
const NodeOperationHash &
hash : hashes) {
478 if (prev_hash && *prev_hash ==
hash) {
479 merge_equal_operations(prev_hash->get_operation(),
hash.get_operation());
485 check_for_next_merge = any_merged;
489void NodeOperationBuilder::merge_equal_operations(NodeOperation *from, NodeOperation *into)
491 unlink_inputs_and_relink_outputs(from, into);
492 operations_.remove_first_occurrence_and_reorder(from);
500 for (
const Link &link : links_) {
501 if (link.from() ==
output) {
502 inputs.append(link.to());
508using Tags = std::set<NodeOperation *>;
512 if (reachable.find(op) != reachable.end()) {
515 reachable.insert(op);
519 if (input->is_connected()) {
530 if (op->is_output_operation(context_->
is_rendering())) {
538 if (reachable.find(op) != reachable.end()) {
546 operations_ = reachable_ops;
561 if (input->is_connected()) {
572 sorted.
reserve(operations_.size());
579 operations_ = sorted;
592 os <<
"# Builder start\n";
593 os <<
"digraph G {\n";
594 os <<
" rankdir=LR;\n";
595 os <<
" node [shape=box];\n";
597 os <<
" op" << operation->get_id() <<
" [label=\"" << *operation <<
"\"];\n";
602 os <<
" op" << link.from()->get_operation().get_id() <<
" -> op"
603 << link.to()->get_operation().get_id() <<
";\n";
607 os <<
"# Builder end\n";
#define BLI_assert_unreachable()
MINLINE void zero_v4(float r[4])
MINLINE void zero_v3(float r[3])
bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b)
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
constexpr bool is_empty() const
void append(const T &value)
void insert(const int64_t insert_index, const T &value)
void reserve(const int64_t min_capacity)
Overall context of the compositor.
const bNodeTree * get_bnodetree() const
get the bnodetree of the context
bool is_rendering() const
get the rendering field of the context
bke::bNodeInstanceHash * get_preview_hash() const
get the preview image hash table
Scene * get_scene() const
static void node_to_operations(const Node *node)
static void graphviz(const ExecutionSystem *system, StringRefNull name="")
the ExecutionSystem contains the whole compositor tree.
void set_operations(Span< NodeOperation * > operations)
void from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
Span< Link > links() const
Span< Node * > nodes() const
NodeOperationOutput * from() const
NodeOperationInput * to() const
void map_input_socket(NodeInput *node_socket, NodeOperationInput *operation_socket)
void convert_to_operations(ExecutionSystem *system)
void determine_canvases()
void register_viewer(ViewerOperation *viewer)
Span< Link > get_links() const
void add_preview(NodeOperationOutput *output)
void map_output_socket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
void add_datatype_conversions()
Span< NodeOperation * > get_operations() const
void remove_input_link(NodeOperationInput *to)
void add_node_input_preview(NodeInput *input)
void replace_operation_with_constant(NodeOperation *operation, ConstantOperation *constant_operation)
void add_input_constant_value(NodeOperationInput *input, const NodeInput *node_input)
Vector< NodeOperationInput * > cache_output_links(NodeOperationOutput *output) const
NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree, ExecutionSystem *system)
void add_operation(NodeOperation *operation)
void add_link(NodeOperationOutput *from, NodeOperationInput *to)
void add_operation_input_constants()
NodeOperation & get_operation() const
NodeOperation contains calculation logic.
const void set_node_instance_key(const bNodeInstanceKey &node_instance_key)
void set_name(const std::string name)
void set_id(const int id)
const NodeOperationFlags get_flags() const
unsigned int get_number_of_input_sockets() const
NodeOperationOutput * get_output_socket(unsigned int index=0)
NodeOperationInput * get_input_socket(unsigned int index)
void set_execution_system(ExecutionSystem *system)
NodeOutput are sockets that can send data/input.
bNodeInstanceKey get_instance_key() const
bool is_in_active_group() const
Is this node part of the active group the active group is the group that is currently being edited....
const bNode * get_bnode() const
get the reference to the SDNA bNode struct
void set_channels(const float value[4])
void set_value(float value)
void set_vector(const float vector[3])
void set_active(bool active)
Set< ComponentNode * > visited
@ Vector
Vector data type.
@ Float2
Float2 data type.
static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *op)
NodeOperation * COM_convert_data_type(const NodeOperationOutput &from, const NodeOperationInput &to)
This function will add a date-type conversion rule when the to-socket does not support the from-socke...
static constexpr bool COM_EXPORT_GRAPHVIZ
std::set< NodeOperation * > Tags
void COM_convert_canvas(NodeOperationBuilder &builder, NodeOperationOutput *from_socket, NodeOperationInput *to_socket)
This function will add a resolution rule based on the settings of the NodeInput.
static Vector< NodeOperationHash > generate_hashes(Span< NodeOperation * > operations)
constexpr rcti COM_AREA_NONE
static void sort_operations_recursive(Vector< NodeOperation * > &sorted, Tags &visited, NodeOperation *op)
std::ostream & operator<<(std::ostream &os, const eCompositorPriority &priority)
static blender::bke::bNodeSocketTemplate inputs[]
bNodeRuntimeHandle * runtime
bool use_datatype_conversion