[Bf-blender-cvs] [c71997dd672] functions: initial virtual node tree
Jacques Lucke
noreply at git.blender.org
Mon Jul 22 18:13:07 CEST 2019
Commit: c71997dd672d1a02be54454f63389bd7a81b84ff
Author: Jacques Lucke
Date: Mon Jul 22 14:19:12 2019 +0200
Branches: functions
https://developer.blender.org/rBc71997dd672d1a02be54454f63389bd7a81b84ff
initial virtual node tree
===================================================================
M source/blender/blenkernel/BKE_node_tree.hpp
M source/blender/blenkernel/intern/node_tree.cpp
M source/blender/blenlib/BLI_monotonic_allocator.hpp
M source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
M source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
===================================================================
diff --git a/source/blender/blenkernel/BKE_node_tree.hpp b/source/blender/blenkernel/BKE_node_tree.hpp
index d996cff5a1a..69e0e8958e9 100644
--- a/source/blender/blenkernel/BKE_node_tree.hpp
+++ b/source/blender/blenkernel/BKE_node_tree.hpp
@@ -8,6 +8,7 @@
#include "BLI_small_vector.hpp"
#include "BLI_listbase_wrapper.hpp"
#include "BLI_small_multimap.hpp"
+#include "BLI_monotonic_allocator.hpp"
#include "RNA_access.h"
@@ -15,6 +16,7 @@ namespace BKE {
using BLI::ArrayRef;
using BLI::ListBaseWrapper;
+using BLI::MonotonicAllocator;
using BLI::SmallMap;
using BLI::SmallMultiMap;
using BLI::SmallVector;
@@ -119,4 +121,137 @@ class IndexedNodeTree {
SmallVector<SingleOriginLink> m_single_origin_links;
};
+class VirtualNode;
+class VirtualSocket;
+class VirtualLink;
+
+class VirtualNodeTree {
+ private:
+ bool m_frozen = false;
+ MonotonicAllocator<> m_allocator;
+ SmallVector<VirtualNode *> m_nodes;
+ SmallVector<VirtualLink *> m_links;
+
+ public:
+ VirtualNode *add_bnode(bNodeTree *btree, bNode *bnode);
+ void add_link(VirtualSocket *a, VirtualSocket *b);
+
+ void freeze_and_index();
+
+ ArrayRef<VirtualNode *> nodes()
+ {
+ return m_nodes;
+ }
+
+ ArrayRef<VirtualLink *> links()
+ {
+ return m_links;
+ }
+
+ bool is_frozen()
+ {
+ return m_frozen;
+ }
+
+ private:
+ void initialize_direct_links();
+ void initialize_links();
+};
+
+class VirtualNode {
+ private:
+ friend VirtualNodeTree;
+ friend VirtualSocket;
+
+ VirtualNodeTree *m_backlink;
+ bNodeTree *m_btree;
+ bNode *m_bnode;
+ ArrayRef<VirtualSocket> m_inputs;
+ ArrayRef<VirtualSocket> m_outputs;
+
+ public:
+ ArrayRef<VirtualSocket> inputs()
+ {
+ return m_inputs;
+ }
+
+ ArrayRef<VirtualSocket> outputs()
+ {
+ return m_outputs;
+ }
+
+ VirtualSocket *input(uint index)
+ {
+ return &m_inputs[index];
+ }
+
+ VirtualSocket *output(uint index)
+ {
+ return &m_outputs[index];
+ }
+
+ bNode *bnode()
+ {
+ return m_bnode;
+ }
+};
+
+class VirtualSocket {
+ private:
+ friend VirtualNodeTree;
+
+ VirtualNode *m_vnode;
+ bNodeTree *m_btree;
+ bNodeSocket *m_bsocket;
+
+ ArrayRef<VirtualSocket *> m_direct_links;
+ ArrayRef<VirtualSocket *> m_links;
+
+ public:
+ bool is_input() const
+ {
+ return m_vnode->m_inputs.contains_ptr(this);
+ }
+
+ bool is_output() const
+ {
+ return m_vnode->m_outputs.contains_ptr(this);
+ }
+
+ bNodeSocket *bsocket()
+ {
+ return m_bsocket;
+ }
+
+ bNodeTree *btree()
+ {
+ return m_btree;
+ }
+
+ VirtualNode *vnode()
+ {
+ return m_vnode;
+ }
+
+ ArrayRef<VirtualSocket *> direct_links()
+ {
+ BLI_assert(m_vnode->m_backlink->is_frozen());
+ return m_direct_links;
+ }
+
+ ArrayRef<VirtualSocket *> links()
+ {
+ BLI_assert(m_vnode->m_backlink->is_frozen());
+ return m_links;
+ }
+};
+
+class VirtualLink {
+ private:
+ friend VirtualNodeTree;
+
+ VirtualSocket *m_from;
+ VirtualSocket *m_to;
+};
+
} // namespace BKE
diff --git a/source/blender/blenkernel/intern/node_tree.cpp b/source/blender/blenkernel/intern/node_tree.cpp
index d9c369a9e05..ee36b754649 100644
--- a/source/blender/blenkernel/intern/node_tree.cpp
+++ b/source/blender/blenkernel/intern/node_tree.cpp
@@ -101,4 +101,137 @@ ArrayRef<SingleOriginLink> IndexedNodeTree::single_origin_links() const
return m_single_origin_links;
}
+/* Virtual Node Tree
+ *****************************************/
+
+VirtualNode *VirtualNodeTree::add_bnode(bNodeTree *btree, bNode *bnode)
+{
+ BLI_assert(!m_frozen);
+
+ VirtualNode *vnode = m_allocator.allocate<VirtualNode>();
+ vnode->m_backlink = this;
+ vnode->m_bnode = bnode;
+ vnode->m_btree = btree;
+
+ SmallVector<bNodeSocket *, 10> original_inputs(bnode->inputs, true);
+ SmallVector<bNodeSocket *, 10> original_outputs(bnode->inputs, true);
+
+ vnode->m_inputs = m_allocator.allocate_array<VirtualSocket>(original_inputs.size());
+ vnode->m_outputs = m_allocator.allocate_array<VirtualSocket>(original_outputs.size());
+
+ for (uint i = 0; i < original_inputs.size(); i++) {
+ VirtualSocket &vsocket = vnode->m_inputs[i];
+ new (&vsocket) VirtualSocket();
+ vsocket.m_vnode = vnode;
+ vsocket.m_btree = btree;
+ vsocket.m_bsocket = original_inputs[i];
+ }
+ for (uint i = 0; i < original_outputs.size(); i++) {
+ VirtualSocket &vsocket = vnode->m_outputs[i];
+ new (&vsocket) VirtualSocket();
+ vsocket.m_vnode = vnode;
+ vsocket.m_btree = btree;
+ vsocket.m_bsocket = original_outputs[i];
+ }
+
+ m_nodes.append(vnode);
+ return vnode;
+}
+
+void VirtualNodeTree::add_link(VirtualSocket *a, VirtualSocket *b)
+{
+ BLI_assert(!m_frozen);
+
+ VirtualLink *vlink = m_allocator.allocate<VirtualLink>();
+ if (a->is_input()) {
+ BLI_assert(b->is_output());
+ vlink->m_from = a;
+ vlink->m_to = b;
+ }
+ else {
+ BLI_assert(b->is_input());
+ vlink->m_from = b;
+ vlink->m_to = a;
+ }
+
+ m_links.append(vlink);
+}
+
+void VirtualNodeTree::freeze_and_index()
+{
+ m_frozen = true;
+ this->initialize_direct_links();
+ this->initialize_links();
+}
+
+BLI_NOINLINE void VirtualNodeTree::initialize_direct_links()
+{
+ /* TODO(jacques): reserve */
+ SmallMultiMap<VirtualSocket *, VirtualSocket *> connections;
+ for (VirtualLink *link : m_links) {
+ connections.add(link->m_from, link->m_to);
+ connections.add(link->m_to, link->m_from);
+ }
+
+ /* TODO(jacques): items iterator */
+ for (VirtualSocket *vsocket : connections.keys()) {
+ auto others = connections.lookup(vsocket);
+ vsocket->m_direct_links = m_allocator.allocate_array<VirtualSocket *>(others.size());
+ vsocket->m_direct_links.copy_from(others);
+ }
+}
+
+static bool is_reroute(VirtualNode *vnode)
+{
+ return STREQ(vnode->bnode()->idname, "NodeReroute");
+}
+
+static void find_connected_sockets_left(VirtualSocket *vsocket,
+ SmallVector<VirtualSocket *> &r_found)
+{
+ BLI_assert(vsocket->is_input());
+ for (VirtualSocket *other : vsocket->direct_links()) {
+ if (is_reroute(other->vnode())) {
+ find_connected_sockets_left(other->vnode()->input(0), r_found);
+ }
+ else {
+ r_found.append(other);
+ }
+ }
+}
+
+static void find_connected_sockets_right(VirtualSocket *vsocket,
+ SmallVector<VirtualSocket *> &r_found)
+{
+ BLI_assert(vsocket->is_output());
+ for (VirtualSocket *other : vsocket->direct_links()) {
+ if (is_reroute(other->vnode())) {
+ find_connected_sockets_right(other->vnode()->output(0), r_found);
+ }
+ else {
+ r_found.append(other);
+ }
+ }
+}
+
+BLI_NOINLINE void VirtualNodeTree::initialize_links()
+{
+ for (VirtualLink *vlink : m_links) {
+ if (vlink->m_from->m_links.size() == 0) {
+ VirtualSocket *vsocket = vlink->m_from;
+ SmallVector<VirtualSocket *> found;
+ find_connected_sockets_right(vsocket, found);
+ vsocket->m_links = m_allocator.allocate_array<VirtualSocket *>(found.size());
+ vsocket->m_links.copy_from(found);
+ }
+ if (vlink->m_to->m_links.size() == 0) {
+ VirtualSocket *vsocket = vlink->m_to;
+ SmallVector<VirtualSocket *> found;
+ find_connected_sockets_left(vsocket, found);
+ vsocket->m_links = m_allocator.allocate_array<VirtualSocket *>(found.size());
+ vsocket->m_links.copy_from(found);
+ }
+ }
+}
+
} // namespace BKE
diff --git a/source/blender/blenlib/BLI_monotonic_allocator.hpp b/source/blender/blenlib/BLI_monotonic_allocator.hpp
index 3fe30299107..bd2b95f180d 100644
--- a/source/blender/blenlib/BLI_monotonic_allocator.hpp
+++ b/source/blender/blenlib/BLI_monotonic_allocator.hpp
@@ -61,6 +61,16 @@ template<uint N = 0> class MonotonicAllocator {
return ptr;
}
}
+
+ template<typename T> T *allocate()
+ {
+ return (T *)this->allocate(sizeof(T));
+ }
+
+ template<typename T> ArrayRef<T> allocate_array(uint length)
+ {
+ return ArrayRef<T>((T *)this->allocate(sizeof(T) * length), length);
+ }
};
} // namespace BLI
diff --git a/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp b/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
index 132fed03859..167e066b720 100644
--- a/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
+++ b/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
@@ -145,6 +145,32 @@ class BasicUnlinkedInputsHandler : public UnlinkedInputsHandler {
Optional<BTreeDataGraph> generate_graph(IndexedNodeTree &indexed_btree)
{
+ bNodeTree *btree = indexed_btree.btree();
+
+ VirtualNodeTree vtree;
+ SmallMap<bNode *, VirtualNode *> node_mapping;
+ for (bNode *bnode : BKE::bNodeList(btree->nodes)) {
+ VirtualNode *vnode = vtree.add_bnode(btree, bnode);
+ node_mapping.add_new(bnode, vnode);
+ }
+ for (bNodeLink *blink : BKE::bLinkList(btree->links)) {
+ VirtualNode *from_node = node_mapping.lookup(blink->fromnode);
+ VirtualNode *to_node = node_mapping.lookup(blink->tonode);
+ VirtualSocket *from_socket = nullptr;
+ VirtualSocket *to_socket = nullptr;
+ for (VirtualSocket &output : from_node->outputs()) {
+ if (output.bsocket() == blink->fromsock) {
+ from_socket = &output;
+ }
+ }
+ for (VirtualSocket &input : to_node->inputs()) {
+ if (input.bsocket() == blink->tosock) {
+ to_socket = &input;
+ }
+ }
+ vtree.add_link(from_socket, to_socket);
+ }
+
DataFlowGraphBuilder graph_builder;
SmallMap<bNodeSocket *, DFGB_Socket> socket_map;
diff --git a/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp b/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
index e384836b7d7..2a87ea5ae1d 100644
--- a/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
+++ b/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
@@ -11,6 +11,10 @@ namespace DataFlowNodes {
using BKE::IndexedNodeTree;
using BKE::SocketWithNode;
+using BKE::VirtualLink;
+using BKE::VirtualNode;
+using BKE::VirtualNodeTree;
+using BKE::VirtualSocket;
class UnlinkedInputsHandler {
public:
More information about the Bf-blender-cvs
mailing list