2020-06-09 17:08:41 +02:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2020-07-17 11:36:59 +02:00
|
|
|
#include "NOD_derived_node_tree.hh"
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
#include "BLI_dot_export.hh"
|
|
|
|
|
|
|
|
#define UNINITIALIZED_ID UINT32_MAX
|
|
|
|
|
2020-07-17 11:36:59 +02:00
|
|
|
namespace blender::nodes {
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-12-02 13:25:25 +01:00
|
|
|
DerivedNodeTree::DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs) : btree_(btree)
|
2020-06-09 17:08:41 +02:00
|
|
|
{
|
2020-12-02 13:25:25 +01:00
|
|
|
BLI_assert(btree != nullptr);
|
|
|
|
|
2021-03-04 18:15:22 +01:00
|
|
|
const NodeTreeRef &main_tree_ref = get_tree_ref_from_map(node_tree_refs, *btree);
|
2020-12-02 13:25:25 +01:00
|
|
|
used_node_tree_refs_.add_new(&main_tree_ref);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
Vector<DNode *> all_nodes;
|
|
|
|
Vector<DGroupInput *> all_group_inputs;
|
|
|
|
Vector<DParentNode *> all_parent_nodes;
|
|
|
|
|
|
|
|
this->insert_nodes_and_links_in_id_order(main_tree_ref, nullptr, all_nodes);
|
|
|
|
this->expand_groups(all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs);
|
2020-11-27 19:38:14 +01:00
|
|
|
this->relink_and_remove_muted_nodes(all_nodes);
|
2020-06-09 17:08:41 +02:00
|
|
|
this->remove_expanded_group_interfaces(all_nodes);
|
|
|
|
this->remove_unused_group_inputs(all_group_inputs);
|
|
|
|
this->store_in_this_and_init_ids(
|
|
|
|
std::move(all_nodes), std::move(all_group_inputs), std::move(all_parent_nodes));
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::insert_nodes_and_links_in_id_order(const NodeTreeRef &tree_ref,
|
|
|
|
DParentNode *parent,
|
|
|
|
Vector<DNode *> &all_nodes)
|
|
|
|
{
|
|
|
|
Array<DSocket *, 64> sockets_map(tree_ref.sockets().size());
|
|
|
|
|
|
|
|
/* Insert nodes. */
|
|
|
|
for (const NodeRef *node_ref : tree_ref.nodes()) {
|
|
|
|
DNode &node = this->create_node(*node_ref, parent, sockets_map);
|
|
|
|
all_nodes.append(&node);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Insert links. */
|
|
|
|
for (const NodeRef *node_ref : tree_ref.nodes()) {
|
|
|
|
for (const InputSocketRef *to_socket_ref : node_ref->inputs()) {
|
2020-08-07 18:24:59 +02:00
|
|
|
DInputSocket *to_socket = static_cast<DInputSocket *>(sockets_map[to_socket_ref->id()]);
|
2020-06-09 17:08:41 +02:00
|
|
|
for (const OutputSocketRef *from_socket_ref : to_socket_ref->linked_sockets()) {
|
2020-08-07 18:24:59 +02:00
|
|
|
DOutputSocket *from_socket = static_cast<DOutputSocket *>(
|
|
|
|
sockets_map[from_socket_ref->id()]);
|
2020-07-03 14:15:05 +02:00
|
|
|
to_socket->linked_sockets_.append(from_socket);
|
|
|
|
from_socket->linked_sockets_.append(to_socket);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DNode &DerivedNodeTree::create_node(const NodeRef &node_ref,
|
|
|
|
DParentNode *parent,
|
|
|
|
MutableSpan<DSocket *> r_sockets_map)
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
DNode &node = *allocator_.construct<DNode>();
|
|
|
|
node.node_ref_ = &node_ref;
|
|
|
|
node.parent_ = parent;
|
|
|
|
node.id_ = UNINITIALIZED_ID;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
node.inputs_ = allocator_.construct_elements_and_pointer_array<DInputSocket>(
|
2020-06-09 17:08:41 +02:00
|
|
|
node_ref.inputs().size());
|
2020-07-03 14:15:05 +02:00
|
|
|
node.outputs_ = allocator_.construct_elements_and_pointer_array<DOutputSocket>(
|
2020-06-09 17:08:41 +02:00
|
|
|
node_ref.outputs().size());
|
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int i : node.inputs_.index_range()) {
|
2020-06-09 17:08:41 +02:00
|
|
|
const InputSocketRef &socket_ref = node_ref.input(i);
|
2020-07-03 14:15:05 +02:00
|
|
|
DInputSocket &socket = *node.inputs_[i];
|
2021-02-03 11:02:01 -06:00
|
|
|
socket.is_multi_input_socket_ = socket_ref.bsocket()->flag & SOCK_MULTI_INPUT;
|
2020-07-03 14:15:05 +02:00
|
|
|
socket.id_ = UNINITIALIZED_ID;
|
|
|
|
socket.node_ = &node;
|
|
|
|
socket.socket_ref_ = &socket_ref;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
r_sockets_map[socket_ref.id()] = &socket;
|
|
|
|
}
|
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int i : node.outputs_.index_range()) {
|
2020-06-09 17:08:41 +02:00
|
|
|
const OutputSocketRef &socket_ref = node_ref.output(i);
|
2020-07-03 14:15:05 +02:00
|
|
|
DOutputSocket &socket = *node.outputs_[i];
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
socket.id_ = UNINITIALIZED_ID;
|
|
|
|
socket.node_ = &node;
|
|
|
|
socket.socket_ref_ = &socket_ref;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
r_sockets_map[socket_ref.id()] = &socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::expand_groups(Vector<DNode *> &all_nodes,
|
|
|
|
Vector<DGroupInput *> &all_group_inputs,
|
|
|
|
Vector<DParentNode *> &all_parent_nodes,
|
|
|
|
NodeTreeRefMap &node_tree_refs)
|
|
|
|
{
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int i = 0; i < all_nodes.size(); i++) {
|
2020-06-09 17:08:41 +02:00
|
|
|
DNode &node = *all_nodes[i];
|
2020-07-03 14:15:05 +02:00
|
|
|
if (node.node_ref_->is_group_node()) {
|
2020-11-27 19:38:14 +01:00
|
|
|
/* Muted nodes are relinked in a separate step. */
|
|
|
|
if (!node.node_ref_->is_muted()) {
|
|
|
|
this->expand_group_node(
|
|
|
|
node, all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs);
|
|
|
|
}
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::expand_group_node(DNode &group_node,
|
|
|
|
Vector<DNode *> &all_nodes,
|
|
|
|
Vector<DGroupInput *> &all_group_inputs,
|
|
|
|
Vector<DParentNode *> &all_parent_nodes,
|
|
|
|
NodeTreeRefMap &node_tree_refs)
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
const NodeRef &group_node_ref = *group_node.node_ref_;
|
2020-06-09 17:08:41 +02:00
|
|
|
BLI_assert(group_node_ref.is_group_node());
|
|
|
|
|
2020-08-07 18:24:59 +02:00
|
|
|
bNodeTree *btree = reinterpret_cast<bNodeTree *>(group_node_ref.bnode()->id);
|
2020-06-09 17:08:41 +02:00
|
|
|
if (btree == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-04 18:15:22 +01:00
|
|
|
const NodeTreeRef &group_ref = get_tree_ref_from_map(node_tree_refs, *btree);
|
2020-12-02 13:25:25 +01:00
|
|
|
used_node_tree_refs_.add(&group_ref);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
DParentNode &parent = *allocator_.construct<DParentNode>();
|
|
|
|
parent.id_ = all_parent_nodes.append_and_get_index(&parent);
|
|
|
|
parent.parent_ = group_node.parent_;
|
|
|
|
parent.node_ref_ = &group_node_ref;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
this->insert_nodes_and_links_in_id_order(group_ref, &parent, all_nodes);
|
|
|
|
Span<DNode *> new_nodes_by_id = all_nodes.as_span().take_back(group_ref.nodes().size());
|
|
|
|
|
|
|
|
this->create_group_inputs_for_unlinked_inputs(group_node, all_group_inputs);
|
|
|
|
this->relink_group_inputs(group_ref, new_nodes_by_id, group_node);
|
|
|
|
this->relink_group_outputs(group_ref, new_nodes_by_id, group_node);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::create_group_inputs_for_unlinked_inputs(
|
|
|
|
DNode &node, Vector<DGroupInput *> &all_group_inputs)
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *input_socket : node.inputs_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
if (input_socket->is_linked()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
DGroupInput &group_input = *allocator_.construct<DGroupInput>();
|
|
|
|
group_input.id_ = UNINITIALIZED_ID;
|
|
|
|
group_input.socket_ref_ = &input_socket->socket_ref();
|
|
|
|
group_input.parent_ = node.parent_;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
group_input.linked_sockets_.append(input_socket);
|
|
|
|
input_socket->linked_group_inputs_.append(&group_input);
|
2020-06-09 17:08:41 +02:00
|
|
|
all_group_inputs.append(&group_input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::relink_group_inputs(const NodeTreeRef &group_ref,
|
|
|
|
Span<DNode *> nodes_by_id,
|
|
|
|
DNode &group_node)
|
|
|
|
{
|
2020-06-30 13:35:38 +02:00
|
|
|
Span<const NodeRef *> node_refs = group_ref.nodes_by_type("NodeGroupInput");
|
2020-06-09 17:08:41 +02:00
|
|
|
if (node_refs.size() == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
int input_amount = group_node.inputs().size();
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int input_index : IndexRange(input_amount)) {
|
2020-07-03 14:15:05 +02:00
|
|
|
DInputSocket *outside_group = group_node.inputs_[input_index];
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DOutputSocket *outside_connected : outside_group->linked_sockets_) {
|
|
|
|
outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) {
|
|
|
|
outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:50:23 +01:00
|
|
|
for (const NodeRef *input_node_ref : node_refs) {
|
|
|
|
DNode &input_node = *nodes_by_id[input_node_ref->id()];
|
|
|
|
DOutputSocket *inside_group = input_node.outputs_[input_index];
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2021-03-04 12:50:23 +01:00
|
|
|
for (DInputSocket *inside_connected : inside_group->linked_sockets_) {
|
|
|
|
inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group);
|
|
|
|
|
|
|
|
for (DOutputSocket *outside_connected : outside_group->linked_sockets_) {
|
|
|
|
inside_connected->linked_sockets_.append(outside_connected);
|
|
|
|
outside_connected->linked_sockets_.append(inside_connected);
|
|
|
|
}
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2021-03-04 12:50:23 +01:00
|
|
|
for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) {
|
|
|
|
inside_connected->linked_group_inputs_.append(outside_connected);
|
|
|
|
outside_connected->linked_sockets_.append(inside_connected);
|
|
|
|
}
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
2021-03-04 12:50:23 +01:00
|
|
|
|
|
|
|
inside_group->linked_sockets_.clear();
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
outside_group->linked_sockets_.clear();
|
|
|
|
outside_group->linked_group_inputs_.clear();
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::relink_group_outputs(const NodeTreeRef &group_ref,
|
|
|
|
Span<DNode *> nodes_by_id,
|
|
|
|
DNode &group_node)
|
|
|
|
{
|
2020-06-30 13:35:38 +02:00
|
|
|
Span<const NodeRef *> node_refs = group_ref.nodes_by_type("NodeGroupOutput");
|
2020-06-09 17:08:41 +02:00
|
|
|
if (node_refs.size() == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* TODO: Pick correct group output node if there are more than one. */
|
|
|
|
const NodeRef &output_node_ref = *node_refs[0];
|
|
|
|
DNode &output_node = *nodes_by_id[output_node_ref.id()];
|
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
int output_amount = group_node.outputs().size();
|
2020-06-09 17:08:41 +02:00
|
|
|
BLI_assert(output_amount == output_node_ref.inputs().size() - 1);
|
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int output_index : IndexRange(output_amount)) {
|
2020-07-03 14:15:05 +02:00
|
|
|
DOutputSocket *outside_group = group_node.outputs_[output_index];
|
|
|
|
DInputSocket *inside_group = output_node.inputs_[output_index];
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *outside_connected : outside_group->linked_sockets_) {
|
|
|
|
outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DOutputSocket *inside_connected : inside_group->linked_sockets_) {
|
|
|
|
inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *outside_connected : outside_group->linked_sockets_) {
|
|
|
|
inside_connected->linked_sockets_.append(outside_connected);
|
|
|
|
outside_connected->linked_sockets_.append(inside_connected);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DGroupInput *inside_connected : inside_group->linked_group_inputs_) {
|
|
|
|
inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *outside_connected : outside_group->linked_sockets_) {
|
|
|
|
inside_connected->linked_sockets_.append(outside_connected);
|
|
|
|
outside_connected->linked_group_inputs_.append(inside_connected);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
outside_group->linked_sockets_.clear();
|
|
|
|
inside_group->linked_sockets_.clear();
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::remove_expanded_group_interfaces(Vector<DNode *> &all_nodes)
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
while (index < all_nodes.size()) {
|
|
|
|
DNode &node = *all_nodes[index];
|
2020-07-03 14:15:05 +02:00
|
|
|
const NodeRef &node_ref = *node.node_ref_;
|
2020-06-09 17:08:41 +02:00
|
|
|
if (node_ref.is_group_node() ||
|
2020-07-03 14:15:05 +02:00
|
|
|
(node.parent_ != nullptr &&
|
2020-06-09 17:08:41 +02:00
|
|
|
(node_ref.is_group_input_node() || node_ref.is_group_output_node()))) {
|
|
|
|
all_nodes.remove_and_reorder(index);
|
|
|
|
node.destruct_with_sockets();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::remove_unused_group_inputs(
|
|
|
|
Vector<DGroupInput *> &all_group_inputs)
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
while (index < all_group_inputs.size()) {
|
|
|
|
DGroupInput &group_input = *all_group_inputs[index];
|
2020-07-03 14:15:05 +02:00
|
|
|
if (group_input.linked_sockets_.is_empty()) {
|
2020-06-09 17:08:41 +02:00
|
|
|
all_group_inputs.remove_and_reorder(index);
|
|
|
|
group_input.~DGroupInput();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-27 19:38:14 +01:00
|
|
|
BLI_NOINLINE void DerivedNodeTree::relink_and_remove_muted_nodes(Vector<DNode *> &all_nodes)
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
while (index < all_nodes.size()) {
|
|
|
|
DNode &node = *all_nodes[index];
|
|
|
|
const NodeRef &node_ref = *node.node_ref_;
|
|
|
|
if (node_ref.is_muted()) {
|
|
|
|
this->relink_muted_node(node);
|
|
|
|
all_nodes.remove_and_reorder(index);
|
|
|
|
node.destruct_with_sockets();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::relink_muted_node(DNode &node)
|
|
|
|
{
|
|
|
|
const bNode &bnode = *node.bnode();
|
|
|
|
LISTBASE_FOREACH (const bNodeLink *, internal_link, &bnode.internal_links) {
|
|
|
|
BLI_assert(internal_link->fromnode == &bnode);
|
|
|
|
BLI_assert(internal_link->tonode == &bnode);
|
|
|
|
bNodeSocket *input_bsocket = internal_link->fromsock;
|
|
|
|
bNodeSocket *output_bsocket = internal_link->tosock;
|
|
|
|
|
|
|
|
/* Find internally linked sockets. */
|
|
|
|
DInputSocket *input_socket = nullptr;
|
|
|
|
DOutputSocket *output_socket = nullptr;
|
|
|
|
for (DInputSocket *socket : node.inputs_) {
|
|
|
|
if (socket->bsocket() == input_bsocket) {
|
|
|
|
input_socket = socket;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (DOutputSocket *socket : node.outputs_) {
|
|
|
|
if (socket->bsocket() == output_bsocket) {
|
|
|
|
output_socket = socket;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BLI_assert(input_socket != nullptr);
|
|
|
|
BLI_assert(output_socket != nullptr);
|
|
|
|
|
|
|
|
/* Link sockets connected to the input to sockets that are connected to the internally linked
|
|
|
|
* output. */
|
|
|
|
for (DInputSocket *to_socket : output_socket->linked_sockets_) {
|
|
|
|
for (DOutputSocket *from_socket : input_socket->linked_sockets_) {
|
|
|
|
from_socket->linked_sockets_.append_non_duplicates(to_socket);
|
|
|
|
to_socket->linked_sockets_.append_non_duplicates(from_socket);
|
|
|
|
}
|
|
|
|
for (DGroupInput *group_input : input_socket->linked_group_inputs_) {
|
|
|
|
group_input->linked_sockets_.append_non_duplicates(to_socket);
|
|
|
|
to_socket->linked_group_inputs_.append_non_duplicates(group_input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove remaining links from muted node. */
|
|
|
|
for (DInputSocket *to_socket : node.inputs_) {
|
|
|
|
for (DOutputSocket *from_socket : to_socket->linked_sockets_) {
|
|
|
|
from_socket->linked_sockets_.remove_first_occurrence_and_reorder(to_socket);
|
|
|
|
}
|
|
|
|
for (DGroupInput *from_group_input : to_socket->linked_group_inputs_) {
|
|
|
|
from_group_input->linked_sockets_.remove_first_occurrence_and_reorder(to_socket);
|
|
|
|
}
|
|
|
|
to_socket->linked_sockets_.clear();
|
|
|
|
to_socket->linked_group_inputs_.clear();
|
|
|
|
}
|
|
|
|
for (DOutputSocket *from_socket : node.outputs_) {
|
|
|
|
for (DInputSocket *to_socket : from_socket->linked_sockets_) {
|
|
|
|
to_socket->linked_sockets_.remove_first_occurrence_and_reorder(from_socket);
|
|
|
|
}
|
|
|
|
from_socket->linked_sockets_.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-09 17:08:41 +02:00
|
|
|
void DNode::destruct_with_sockets()
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *socket : inputs_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
socket->~DInputSocket();
|
|
|
|
}
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DOutputSocket *socket : outputs_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
socket->~DOutputSocket();
|
|
|
|
}
|
|
|
|
this->~DNode();
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_NOINLINE void DerivedNodeTree::store_in_this_and_init_ids(
|
|
|
|
Vector<DNode *> &&all_nodes,
|
|
|
|
Vector<DGroupInput *> &&all_group_inputs,
|
|
|
|
Vector<DParentNode *> &&all_parent_nodes)
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
nodes_by_id_ = std::move(all_nodes);
|
|
|
|
group_inputs_ = std::move(all_group_inputs);
|
|
|
|
parent_nodes_ = std::move(all_parent_nodes);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int node_index : nodes_by_id_.index_range()) {
|
2020-07-03 14:15:05 +02:00
|
|
|
DNode *node = nodes_by_id_[node_index];
|
|
|
|
node->id_ = node_index;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
const bNodeType *nodetype = node->node_ref_->bnode()->typeinfo;
|
2020-07-24 12:15:13 +02:00
|
|
|
nodes_by_type_.add(nodetype, node);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *socket : node->inputs_) {
|
|
|
|
socket->id_ = sockets_by_id_.append_and_get_index(socket);
|
|
|
|
input_sockets_.append(socket);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DOutputSocket *socket : node->outputs_) {
|
|
|
|
socket->id_ = sockets_by_id_.append_and_get_index(socket);
|
|
|
|
output_sockets_.append(socket);
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-20 12:16:20 +02:00
|
|
|
for (int i : group_inputs_.index_range()) {
|
2020-07-03 14:15:05 +02:00
|
|
|
group_inputs_[i]->id_ = i;
|
2020-06-09 17:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DerivedNodeTree::~DerivedNodeTree()
|
|
|
|
{
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DInputSocket *socket : input_sockets_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
socket->~DInputSocket();
|
|
|
|
}
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DOutputSocket *socket : output_sockets_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
socket->~DOutputSocket();
|
|
|
|
}
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DNode *node : nodes_by_id_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
node->~DNode();
|
|
|
|
}
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DGroupInput *group_input : group_inputs_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
group_input->~DGroupInput();
|
|
|
|
}
|
2020-07-03 14:15:05 +02:00
|
|
|
for (DParentNode *parent : parent_nodes_) {
|
2020-06-09 17:08:41 +02:00
|
|
|
parent->~DParentNode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-02 13:25:25 +01:00
|
|
|
bool DerivedNodeTree::has_link_cycles() const
|
|
|
|
{
|
|
|
|
for (const NodeTreeRef *tree : used_node_tree_refs_) {
|
|
|
|
if (tree->has_link_cycles()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-06-29 11:53:17 +02:00
|
|
|
static dot::Cluster *get_cluster_for_parent(dot::DirectedGraph &graph,
|
|
|
|
Map<const DParentNode *, dot::Cluster *> &clusters,
|
2020-06-09 17:08:41 +02:00
|
|
|
const DParentNode *parent)
|
|
|
|
{
|
|
|
|
if (parent == nullptr) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2020-06-10 14:12:24 +02:00
|
|
|
return clusters.lookup_or_add_cb(parent, [&]() {
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::Cluster *parent_cluster = get_cluster_for_parent(graph, clusters, parent->parent());
|
2020-08-07 18:24:59 +02:00
|
|
|
bNodeTree *btree = reinterpret_cast<bNodeTree *>(parent->node_ref().bnode()->id);
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::Cluster *new_cluster = &graph.new_cluster(parent->node_ref().name() + " / " +
|
2020-06-09 17:08:41 +02:00
|
|
|
StringRef(btree->id.name + 2));
|
|
|
|
new_cluster->set_parent_cluster(parent_cluster);
|
|
|
|
return new_cluster;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string DerivedNodeTree::to_dot() const
|
|
|
|
{
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::DirectedGraph digraph;
|
|
|
|
digraph.set_rankdir(dot::Attr_rankdir::LeftToRight);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-06-29 11:53:17 +02:00
|
|
|
Map<const DNode *, dot::NodeWithSocketsRef> dot_nodes;
|
|
|
|
Map<const DGroupInput *, dot::NodeWithSocketsRef> dot_group_inputs;
|
|
|
|
Map<const DParentNode *, dot::Cluster *> dot_clusters;
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (const DNode *node : nodes_by_id_) {
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::Node &dot_node = digraph.new_node("");
|
2020-06-09 17:08:41 +02:00
|
|
|
dot_node.set_background_color("white");
|
|
|
|
|
|
|
|
Vector<std::string> input_names;
|
|
|
|
for (const DInputSocket *socket : node->inputs()) {
|
|
|
|
input_names.append(socket->name());
|
|
|
|
}
|
|
|
|
Vector<std::string> output_names;
|
|
|
|
for (const DOutputSocket *socket : node->outputs()) {
|
|
|
|
output_names.append(socket->name());
|
|
|
|
}
|
|
|
|
|
|
|
|
dot_nodes.add_new(node,
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names));
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::Cluster *cluster = get_cluster_for_parent(digraph, dot_clusters, node->parent());
|
2020-06-09 17:08:41 +02:00
|
|
|
dot_node.set_parent_cluster(cluster);
|
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (const DGroupInput *group_input : group_inputs_) {
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::Node &dot_node = digraph.new_node("");
|
2020-06-09 17:08:41 +02:00
|
|
|
dot_node.set_background_color("white");
|
|
|
|
|
|
|
|
std::string group_input_name = group_input->name();
|
|
|
|
dot_group_inputs.add_new(
|
2020-06-29 11:53:17 +02:00
|
|
|
group_input, dot::NodeWithSocketsRef(dot_node, "Group Input", {}, {group_input_name}));
|
2020-06-09 17:08:41 +02:00
|
|
|
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::Cluster *cluster = get_cluster_for_parent(digraph, dot_clusters, group_input->parent());
|
2020-06-09 17:08:41 +02:00
|
|
|
dot_node.set_parent_cluster(cluster);
|
|
|
|
}
|
|
|
|
|
2020-07-03 14:15:05 +02:00
|
|
|
for (const DNode *to_node : nodes_by_id_) {
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(to_node);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
for (const DInputSocket *to_socket : to_node->inputs()) {
|
|
|
|
for (const DOutputSocket *from_socket : to_socket->linked_sockets()) {
|
|
|
|
const DNode *from_node = &from_socket->node();
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(from_node);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
digraph.new_edge(from_dot_node.output(from_socket->index()),
|
|
|
|
to_dot_node.input(to_socket->index()));
|
|
|
|
}
|
|
|
|
for (const DGroupInput *group_input : to_socket->linked_group_inputs()) {
|
2020-06-29 11:53:17 +02:00
|
|
|
dot::NodeWithSocketsRef &from_dot_node = dot_group_inputs.lookup(group_input);
|
2020-06-09 17:08:41 +02:00
|
|
|
|
|
|
|
digraph.new_edge(from_dot_node.output(0), to_dot_node.input(to_socket->index()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
digraph.set_random_cluster_bgcolors();
|
|
|
|
return digraph.to_dot_string();
|
|
|
|
}
|
|
|
|
|
2020-07-17 11:36:59 +02:00
|
|
|
} // namespace blender::nodes
|