[Bf-blender-cvs] [7e4f9880722] master: BLI: improve node graph export in dot format
Jacques Lucke
noreply at git.blender.org
Thu Dec 29 15:10:00 CET 2022
Commit: 7e4f9880722a82b59acf1c18ae234935bed02aff
Author: Jacques Lucke
Date: Thu Dec 29 15:09:52 2022 +0100
Branches: master
https://developer.blender.org/rB7e4f9880722a82b59acf1c18ae234935bed02aff
BLI: improve node graph export in dot format
This makes it bit easier to export node graphs and also allows for
more customization of links and sockets.
===================================================================
M source/blender/blenlib/BLI_dot_export.hh
M source/blender/blenlib/intern/dot_export.cc
M source/blender/functions/FN_lazy_function_graph.hh
M source/blender/functions/intern/lazy_function_graph.cc
M source/blender/nodes/intern/derived_node_tree.cc
===================================================================
diff --git a/source/blender/blenlib/BLI_dot_export.hh b/source/blender/blenlib/BLI_dot_export.hh
index 454f3c8412c..cc30d9425ee 100644
--- a/source/blender/blenlib/BLI_dot_export.hh
+++ b/source/blender/blenlib/BLI_dot_export.hh
@@ -184,10 +184,13 @@ class NodePort {
private:
Node *node_;
std::optional<std::string> port_name_;
+ std::optional<std::string> port_position_;
public:
- NodePort(Node &node, std::optional<std::string> port_name = {})
- : node_(&node), port_name_(std::move(port_name))
+ NodePort(Node &node,
+ std::optional<std::string> port_name = {},
+ std::optional<std::string> port_position = {})
+ : node_(&node), port_name_(std::move(port_name)), port_position_(std::move(port_position))
{
}
@@ -248,15 +251,43 @@ class UndirectedEdge : public Edge {
std::string color_attr_from_hsv(float h, float s, float v);
+struct NodeWithSockets {
+ struct Socket {
+ std::string name;
+ std::optional<std::string> fontcolor;
+ };
+ struct Input : public Socket {
+ };
+ struct Output : public Socket {
+ };
+
+ std::string node_name;
+ Vector<Input> inputs;
+ Vector<Output> outputs;
+
+ Input &add_input(std::string name)
+ {
+ this->inputs.append({});
+ Input &input = this->inputs.last();
+ input.name = std::move(name);
+ return input;
+ }
+
+ Output &add_output(std::string name)
+ {
+ this->outputs.append({});
+ Output &output = this->outputs.last();
+ output.name = std::move(name);
+ return output;
+ }
+};
+
class NodeWithSocketsRef {
private:
Node *node_;
public:
- NodeWithSocketsRef(Node &node,
- StringRef name,
- Span<std::string> input_names,
- Span<std::string> output_names);
+ NodeWithSocketsRef(Node &node, const NodeWithSockets &data);
Node &node()
{
@@ -266,13 +297,13 @@ class NodeWithSocketsRef {
NodePort input(int index) const
{
std::string port = "\"in" + std::to_string(index) + "\"";
- return NodePort(*node_, port);
+ return NodePort(*node_, port, "w");
}
NodePort output(int index) const
{
std::string port = "\"out" + std::to_string(index) + "\"";
- return NodePort(*node_, port);
+ return NodePort(*node_, port, "e");
}
};
diff --git a/source/blender/blenlib/intern/dot_export.cc b/source/blender/blenlib/intern/dot_export.cc
index d577de9bc34..8d2bf3f9a5f 100644
--- a/source/blender/blenlib/intern/dot_export.cc
+++ b/source/blender/blenlib/intern/dot_export.cc
@@ -244,6 +244,9 @@ void NodePort::to_dot_string(std::stringstream &ss) const
if (port_name_.has_value()) {
ss << ":" << *port_name_;
}
+ if (port_position_.has_value()) {
+ ss << ":" << *port_position_;
+ }
}
std::string color_attr_from_hsv(float h, float s, float v)
@@ -253,11 +256,7 @@ std::string color_attr_from_hsv(float h, float s, float v)
return ss.str();
}
-NodeWithSocketsRef::NodeWithSocketsRef(Node &node,
- StringRef name,
- Span<std::string> input_names,
- Span<std::string> output_names)
- : node_(&node)
+NodeWithSocketsRef::NodeWithSocketsRef(Node &node, const NodeWithSockets &data) : node_(&node)
{
std::stringstream ss;
@@ -265,33 +264,39 @@ NodeWithSocketsRef::NodeWithSocketsRef(Node &node,
/* Header */
ss << R"(<tr><td colspan="3" align="center"><b>)";
- ss << ((name.size() == 0) ? "No Name" : name);
+ ss << (data.node_name.empty() ? "No Name" : data.node_name);
ss << "</b></td></tr>";
/* Sockets */
- int socket_max_amount = std::max(input_names.size(), output_names.size());
+ int socket_max_amount = std::max(data.inputs.size(), data.outputs.size());
for (int i = 0; i < socket_max_amount; i++) {
ss << "<tr>";
- if (i < input_names.size()) {
- StringRef name = input_names[i];
- if (name.size() == 0) {
- name = "No Name";
- }
+ if (i < data.inputs.size()) {
+ const NodeWithSockets::Input &input = data.inputs[i];
ss << R"(<td align="left" port="in)" << i << "\">";
- ss << name;
+ if (input.fontcolor) {
+ ss << R"(<font color=")" << *input.fontcolor << "\">";
+ }
+ ss << (input.name.empty() ? "No Name" : input.name);
+ if (input.fontcolor) {
+ ss << "</font>";
+ }
ss << "</td>";
}
else {
ss << "<td></td>";
}
ss << "<td></td>";
- if (i < output_names.size()) {
- StringRef name = output_names[i];
- if (name.size() == 0) {
- name = "No Name";
- }
+ if (i < data.outputs.size()) {
+ const NodeWithSockets::Output &output = data.outputs[i];
ss << R"(<td align="right" port="out)" << i << "\">";
- ss << name;
+ if (output.fontcolor) {
+ ss << R"(<font color=")" << *output.fontcolor << "\">";
+ }
+ ss << (output.name.empty() ? "No Name" : output.name);
+ if (output.fontcolor) {
+ ss << "</font>";
+ }
ss << "</td>";
}
else {
diff --git a/source/blender/functions/FN_lazy_function_graph.hh b/source/blender/functions/FN_lazy_function_graph.hh
index 7352004b7fe..460e858774f 100644
--- a/source/blender/functions/FN_lazy_function_graph.hh
+++ b/source/blender/functions/FN_lazy_function_graph.hh
@@ -19,6 +19,10 @@
#include "FN_lazy_function.hh"
+namespace blender::dot {
+class DirectedEdge;
+}
+
namespace blender::fn::lazy_function {
class Socket;
@@ -238,10 +242,23 @@ class Graph : NonCopyable, NonMovable {
*/
bool node_indices_are_valid() const;
+ /**
+ * Optional configuration options for the dot graph generation. This allows creating
+ * visualizations for specific purposes.
+ */
+ class ToDotOptions {
+ public:
+ virtual std::string socket_name(const Socket &socket) const;
+ virtual std::optional<std::string> socket_font_color(const Socket &socket) const;
+ virtual void add_edge_attributes(const OutputSocket &from,
+ const InputSocket &to,
+ dot::DirectedEdge &dot_edge) const;
+ };
+
/**
* Utility to generate a dot graph string for the graph. This can be used for debugging.
*/
- std::string to_dot() const;
+ std::string to_dot(const ToDotOptions &options = {}) const;
};
/* -------------------------------------------------------------------- */
diff --git a/source/blender/functions/intern/lazy_function_graph.cc b/source/blender/functions/intern/lazy_function_graph.cc
index 60605a4e64c..e8a20fbf9a3 100644
--- a/source/blender/functions/intern/lazy_function_graph.cc
+++ b/source/blender/functions/intern/lazy_function_graph.cc
@@ -152,7 +152,23 @@ std::string DummyDebugInfo::output_name(const int /*i*/) const
return fallback_name;
}
-std::string Graph::to_dot() const
+std::string Graph::ToDotOptions::socket_name(const Socket &socket) const
+{
+ return socket.name();
+}
+
+std::optional<std::string> Graph::ToDotOptions::socket_font_color(const Socket & /*socket*/) const
+{
+ return std::nullopt;
+}
+
+void Graph::ToDotOptions::add_edge_attributes(const OutputSocket & /*from*/,
+ const InputSocket & /*to*/,
+ dot::DirectedEdge & /*dot_edge*/) const
+{
+}
+
+std::string Graph::to_dot(const ToDotOptions &options) const
{
dot::DirectedGraph digraph;
digraph.set_rankdir(dot::Attr_rankdir::LeftToRight);
@@ -168,17 +184,20 @@ std::string Graph::to_dot() const
dot_node.set_background_color("white");
}
- Vector<std::string> input_names;
- Vector<std::string> output_names;
+ dot::NodeWithSockets dot_node_with_sockets;
+ dot_node_with_sockets.node_name = node->name();
for (const InputSocket *socket : node->inputs()) {
- input_names.append(socket->name());
+ dot::NodeWithSockets::Input &dot_input = dot_node_with_sockets.add_input(
+ options.socket_name(*socket));
+ dot_input.fontcolor = options.socket_font_color(*socket);
}
for (const OutputSocket *socket : node->outputs()) {
- output_names.append(socket->name());
+ dot::NodeWithSockets::Output &dot_output = dot_node_with_sockets.add_output(
+ options.socket_name(*socket));
+ dot_output.fontcolor = options.socket_font_color(*socket);
}
- dot_nodes.add_new(node,
- dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names));
+ dot_nodes.add_new(node, dot::NodeWithSocketsRef(dot_node, dot_node_with_sockets));
}
for (const Node *node : nodes_) {
@@ -188,7 +207,9 @@ std::string Graph::to_dot() const
if (const OutputSocket *origin = socket->origin()) {
dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(&origin->node());
- digraph.new_edge(from_dot_node.output(origin->index()), to_dot_port);
+ dot::DirectedEdge &dot_edge = digraph.new_edge(from_dot_node.output(origin->index()),
+ to_dot_port);
+ options.add_edge_attributes(*origin, *socket, dot_edge);
}
else if (const void *default_value = socket->default_value()) {
const CPPType &type = socket->type();
diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc
index ece60ffe4ab..9b8a9f2401a 100644
--- a/source/blender/nodes/intern/derived_node_tree.cc
+++ b/source/blender/nodes/intern/derived_node_tree.cc
@@ -344,27 +344,26 @@ std::string DerivedNodeTree::to_dot() const
dot_node.set_parent_cluster(cluster);
dot_node.set_background_color("white");
- Vector<std::string> input_names;
- Vector<std::string> output_names;
+ dot::NodeWithSockets dot_node_with_sockets;
for (const bNodeSocket *socket : node->input_sockets()) {
if (socket->is_available()) {
- input_names.append(socket->name);
+ dot_node_with_sockets.add_input(socket->name);
}
}
for (const bNodeSocket *socket : node->output_sockets()) {
if (socket->is_available()) {
- output_names.append(socket->name);
+ dot_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list