[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