[Bf-blender-cvs] [fff8781973c] functions: dot export for data flow graph
Jacques Lucke
noreply at git.blender.org
Sun Feb 10 20:25:56 CET 2019
Commit: fff8781973c8b72f5012bc30df3f20e22c7ef147
Author: Jacques Lucke
Date: Mon Feb 4 15:38:27 2019 +0100
Branches: functions
https://developer.blender.org/rBfff8781973c8b72f5012bc30df3f20e22c7ef147
dot export for data flow graph
===================================================================
M source/blender/functions/CMakeLists.txt
M source/blender/functions/c_wrapper.cpp
M source/blender/functions/core/core.hpp
M source/blender/functions/core/data_flow_graph.cpp
M source/blender/functions/core/data_flow_graph.hpp
A source/blender/functions/core/dot_export.cpp
===================================================================
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
index 4d4ae0ebc48..efc9d2a6d7e 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -14,6 +14,7 @@ set(SRC
core/data_flow_graph.hpp
core/cpu.hpp
core/data_flow_graph.cpp
+ core/dot_export.cpp
FN_functions.hpp
diff --git a/source/blender/functions/c_wrapper.cpp b/source/blender/functions/c_wrapper.cpp
index c7823794410..56cc18b4988 100644
--- a/source/blender/functions/c_wrapper.cpp
+++ b/source/blender/functions/c_wrapper.cpp
@@ -3,6 +3,8 @@
#include "./types/types.hpp"
+#include <iostream>
+
#define WRAPPERS(T1, T2) \
inline T1 unwrap(T2 value) { return (T1)value; } \
inline T2 wrap(T1 value) { return (T2)value; }
@@ -111,6 +113,28 @@ public:
}
};
+template<typename T>
+class PassThroughBody : public FN::TupleCallBody {
+public:
+ virtual void call(const FN::Tuple &fn_in, FN::Tuple &fn_out) const override
+ {
+ fn_out.set<T>(0, fn_in.get<T>(0));
+ }
+};
+
+static FN::Function *get_pass_through_float_function()
+{
+ FN::InputParameters inputs;
+ inputs.append(FN::InputParameter("In", FN::Types::float_ty));
+
+ FN::OutputParameters outputs;
+ outputs.append(FN::OutputParameter("Out", FN::Types::float_ty));
+
+ auto fn = new FN::Function(FN::Signature(inputs, outputs), "Pass Through");
+ fn->add_body(new PassThroughBody<float>());
+ return fn;
+}
+
FnFunction FN_get_deform_function(int type)
{
FN::InputParameters inputs;
@@ -120,12 +144,30 @@ FnFunction FN_get_deform_function(int type)
FN::OutputParameters outputs;
outputs.append(FN::OutputParameter("Position", FN::Types::floatvec3d_ty));
- auto fn = new FN::Function(FN::Signature(inputs, outputs));
+ auto fn = new FN::Function(FN::Signature(inputs, outputs), "Deform");
if (type == 0) {
fn->add_body(new Deform1());
}
else {
fn->add_body(new Deform2());
}
+
+ FN::DataFlowGraph graph;
+ const FN::Node *n1 = graph.insert(*fn);
+ const FN::Node *n2 = graph.insert(*fn);
+ const FN::Node *n3 = graph.insert(*fn);
+ const FN::Node *n4 = graph.insert(*fn);
+ const FN::Node *p = graph.insert(*get_pass_through_float_function());
+ graph.link(n1->output(0), n2->input(0));
+ graph.link(n2->output(0), n3->input(0));
+ graph.link(n2->output(0), n4->input(0));
+ graph.link(p->output(0), n1->input(1));
+ graph.link(p->output(0), n2->input(1));
+ graph.link(p->output(0), n3->input(1));
+ graph.link(p->output(0), n4->input(1));
+
+ std::string dot = graph.to_dot();
+ //std::cout << dot << std::endl;
+
return wrap(fn);
}
\ No newline at end of file
diff --git a/source/blender/functions/core/core.hpp b/source/blender/functions/core/core.hpp
index 4c85f58be31..ccf1a96d1c3 100644
--- a/source/blender/functions/core/core.hpp
+++ b/source/blender/functions/core/core.hpp
@@ -150,8 +150,8 @@ namespace FN {
class Function {
public:
- Function(const Signature &signature)
- : m_signature(signature) {}
+ Function(const Signature &signature, const std::string &name = "Function")
+ : m_signature(signature), m_name(name) {}
virtual ~Function() {}
@@ -173,9 +173,15 @@ namespace FN {
this->m_bodies.add(body);
}
+ const std::string &name() const
+ {
+ return this->m_name;
+ }
+
private:
const Signature m_signature;
Composition m_bodies;
+ const std::string m_name;
};
} /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/core/data_flow_graph.cpp b/source/blender/functions/core/data_flow_graph.cpp
index 684310b56dd..61c52b525e8 100644
--- a/source/blender/functions/core/data_flow_graph.cpp
+++ b/source/blender/functions/core/data_flow_graph.cpp
@@ -10,4 +10,14 @@ namespace FN {
return this->node()->signature().inputs()[this->m_index].type();
}
}
+
+ std::string Socket::name() const
+ {
+ if (this->m_is_output) {
+ return this->node()->signature().outputs()[this->m_index].name();
+ }
+ else {
+ return this->node()->signature().inputs()[this->m_index].name();
+ }
+ }
};
\ No newline at end of file
diff --git a/source/blender/functions/core/data_flow_graph.hpp b/source/blender/functions/core/data_flow_graph.hpp
index 727be5a4220..1ea5285c57c 100644
--- a/source/blender/functions/core/data_flow_graph.hpp
+++ b/source/blender/functions/core/data_flow_graph.hpp
@@ -13,15 +13,8 @@ namespace FN {
class Socket {
public:
- static Socket Input(const Node *node, uint index)
- {
- return Socket(node, false, index);
- }
-
- static Socket Output(const Node *node, uint index)
- {
- return Socket(node, true, index);
- }
+ static inline Socket Input(const Node *node, uint index);
+ static inline Socket Output(const Node *node, uint index);
const Node *node() const
{
@@ -44,6 +37,7 @@ namespace FN {
}
const Type *type() const;
+ std::string name() const;
friend bool operator==(const Socket &a, const Socket &b)
{
@@ -91,19 +85,59 @@ namespace FN {
const Function &m_function;
};
+ class Link {
+ public:
+ static Link New(Socket a, Socket b)
+ {
+ BLI_assert(a.is_input() != b.is_input());
+ if (a.is_input()) {
+ return Link(b, a);
+ }
+ else {
+ return Link(a, b);
+ }
+ }
+
+ Socket from() const
+ {
+ return this->m_from;
+ }
+
+ Socket to() const
+ {
+ return this->m_to;
+ }
+
+ friend bool operator==(const Link &a, const Link &b)
+ {
+ return a.m_from == b.m_from && a.m_to == b.m_to;
+ }
+
+ private:
+ Link(Socket from, Socket to)
+ : m_from(from), m_to(to) {}
+
+ const Socket m_from;
+ const Socket m_to;
+ };
+
class GraphLinks {
public:
- void insert(Socket a, Socket b)
+ void insert(Link link)
{
- if (!this->m_links.contains(a)) {
- this->m_links.add(a, SmallSet<Socket>());
+ Socket from = link.from();
+ Socket to = link.to();
+
+ if (!this->m_links.contains(from)) {
+ this->m_links.add(from, SmallSet<Socket>());
}
- if (!this->m_links.contains(b)) {
- this->m_links.add(b, SmallSet<Socket>());
+ if (!this->m_links.contains(to)) {
+ this->m_links.add(to, SmallSet<Socket>());
}
- this->m_links.lookup_ref(a).add(b);
- this->m_links.lookup_ref(b).add(a);
+ this->m_links.lookup_ref(from).add(to);
+ this->m_links.lookup_ref(to).add(from);
+ this->m_all_links.append(Link::New(from, to));
}
SmallSet<Socket> get_linked(Socket socket) const
@@ -111,8 +145,14 @@ namespace FN {
return this->m_links.lookup(socket);
}
+ SmallVector<Link> all_links() const
+ {
+ return this->m_all_links;
+ }
+
private:
SmallMap<Socket, SmallSet<Socket>> m_links;
+ SmallVector<Link> m_all_links;
};
class DataFlowGraph {
@@ -142,8 +182,7 @@ namespace FN {
BLI_assert(m_nodes.contains(a.node()));
BLI_assert(m_nodes.contains(b.node()));
- m_links.insert(a, b);
- m_links.insert(b, a);
+ m_links.insert(Link::New(a, b));
}
inline bool can_modify() const
@@ -161,10 +200,33 @@ namespace FN {
this->m_frozen = true;
}
+ SmallVector<Link> all_links() const
+ {
+ return this->m_links.all_links();
+ }
+
+ std::string to_dot() const;
+
private:
bool m_frozen = false;
SmallSet<const Node *> m_nodes;
GraphLinks m_links;
};
+
+ /* Some inline functions.
+ * Those can only come after the declaration of other types. */
+
+ inline Socket Socket::Input(const Node *node, uint index)
+ {
+ BLI_assert(index < node->signature().inputs().size());
+ return Socket(node, false, index);
+ }
+
+ inline Socket Socket::Output(const Node *node, uint index)
+ {
+ BLI_assert(index < node->signature().outputs().size());
+ return Socket(node, true, index);
+ }
+
} /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/core/dot_export.cpp b/source/blender/functions/core/dot_export.cpp
new file mode 100644
index 00000000000..b1071420a03
--- /dev/null
+++ b/source/blender/functions/core/dot_export.cpp
@@ -0,0 +1,105 @@
+#include "data_flow_graph.hpp"
+
+#include <sstream>
+
+namespace FN {
+ static std::string get_id(const Node *node)
+ {
+ std::stringstream ss;
+ ss << "\"";
+ ss << (void *)node;
+ ss << "\"";
+ return ss.str();
+ }
+
+ static std::string get_id(Socket socket)
+ {
+ std::stringstream ss;
+ ss << "\"";
+ ss << std::to_string(socket.is_input());
+ ss << std::to_string(socket.index());
+ ss << "\"";
+ return ss.str();
+ }
+
+ static std::string port_id(Socket socket)
+ {
+ std::string n = get_id(socket.node());
+ std::string s = get_id(socket);
+ return get_id(socket.node()) + ":" + get_id(socket);
+ }
+
+ static void insert_node_table(std::stringstream &ss, const Node *node)
+ {
+ ss << "<table border=\"0\" cellspacing=\"3\">";
+
+ /* Header */
+ ss << "<tr><td colspan=\"3\" align=\"center\"><b>";
+ ss << node->function().name();
+ ss << "</b></td></tr>";
+
+ /* Sockets */
+ const Signature &sig = node->signature();
+ uint inputs_amount = sig.inputs().size();
+ uint outputs_amount = sig.outputs().size();
+ uint socket_max_amount = std::max(inputs_amount, outputs_amount);
+ for (uint i = 0; i < socket_max_amount; i++) {
+ ss << "<tr>";
+ if (i < inputs_amount) {
+ Socket socket = node->input(i);
+ ss << "<td align=\"left\" port=" << get_id(socket) << ">";
+ ss << socket.name();
+ ss << "</td>";
+ }
+ else {
+ ss << "<td></td>";
+ }
+ ss << "<td></td>";
+ if (i < outputs_amount) {
+ ss << "<td align=\"right\" port=" << get_id(node->output(i)) << ">";
+ ss << node->output(i).name();
+ ss << "</td>";
+ }
+ else {
+ ss << "<td></td>";
+ }
+ ss << "</tr>";
+ }
+
+ ss << "</table>";
+ }
+
+ static void insert_node(std::stringstream &ss, const Node *node)
+ {
+ ss << get_id(node) << " ";
+ ss << "[style=\"filled\", fillcolor=\"#FFFFFF\", shape=\"square\"";
+ ss << ", label=<";
+ insert_node_table(ss, node);
+ ss << ">]";
+ }
+
+ static void insert_link(std::stringstream &ss, Link link)
+ {
+ ss << port_id(link.from()) << " -> " << port_id(link.to());
+ }
+
+ std::string DataFlowGraph::to_dot() const
+ {
+ std::stringstream ss;
+ ss << "digraph MyGraph {" << std::endl;
+ ss << "rankdir=LR" << std::endl;
+
+ for (const Node *node : this->m_nodes) {
+ insert_node(ss, node);
+ ss
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list