Blender V5.0
BLI_dot_export.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
13
14#pragma once
15
16#include "BLI_map.hh"
17#include "BLI_set.hh"
18#include "BLI_utility_mixins.hh"
19#include "BLI_vector.hh"
20
22
23#include <iosfwd>
24#include <optional>
25
26namespace blender::dot_export {
27
28class Graph;
29class DirectedGraph;
30class UndirectedGraph;
31class Node;
32class NodePort;
33class DirectedEdge;
34class UndirectedEdge;
35class Cluster;
36
38 private:
40
41 public:
42 void export__as_bracket_list(std::stringstream &ss) const;
43
44 void set(StringRef key, StringRef value)
45 {
46 attributes_.add_overwrite(key, value);
47 }
48
49 void set(StringRef key, float value)
50 {
51 attributes_.add_overwrite(key, std::to_string(value));
52 }
53};
54
55class Graph {
56 private:
59
60 Set<Node *> top_level_nodes_;
61 Set<Cluster *> top_level_clusters_;
62
63 friend Cluster;
64 friend Node;
65
66 public:
68
69 Node &new_node(StringRef label);
70 Cluster &new_cluster(StringRef label = "");
71
72 void export__declare_nodes_and_clusters(std::stringstream &ss) const;
73
75 {
76 attributes.set("rankdir", rankdir_to_string(rankdir));
77 }
78
80};
81
82class Cluster {
83 private:
84 Graph &graph_;
85 Cluster *parent_ = nullptr;
86 Set<Cluster *> children_;
87 Set<Node *> nodes_;
88
89 friend Graph;
90 friend Node;
91
92 public:
94
95 Cluster(Graph &graph) : graph_(graph) {}
96
97 void export__declare_nodes_and_clusters(std::stringstream &ss) const;
98
99 std::string name() const
100 {
101 return "cluster_" + std::to_string(uintptr_t(this));
102 }
103
104 void set_parent_cluster(Cluster *new_parent);
106 {
107 this->set_parent_cluster(&cluster);
108 }
109
111 {
112 return parent_;
113 }
114
116
117 bool contains(Node &node) const;
118};
119
120class Node {
121 private:
122 Graph &graph_;
123 Cluster *cluster_ = nullptr;
124
125 friend Graph;
126
127 public:
129
130 Node(Graph &graph) : graph_(graph) {}
131
132 void set_parent_cluster(Cluster *cluster);
134 {
135 this->set_parent_cluster(&cluster);
136 }
137
139 {
140 return cluster_;
141 }
142
144 {
145 attributes.set("shape", shape_to_string(shape));
146 }
147
148 /* See https://www.graphviz.org/doc/info/attrs.html#k:color. */
150 {
151 attributes.set("fillcolor", name);
152 attributes.set("style", "filled");
153 }
154
155 void export__as_id(std::stringstream &ss) const;
156
157 void export__as_declaration(std::stringstream &ss) const;
158};
159
161 private:
163
164 public:
165 std::string to_dot_string() const;
166
168};
169
170class DirectedGraph final : public Graph {
171 private:
173
174 public:
175 std::string to_dot_string() const;
176
178};
179
180class NodePort {
181 private:
182 Node *node_;
183 std::optional<std::string> port_name_;
184 std::optional<std::string> port_position_;
185
186 public:
188 std::optional<std::string> port_name = {},
189 std::optional<std::string> port_position = {})
190 : node_(&node), port_name_(std::move(port_name)), port_position_(std::move(port_position))
191 {
192 }
193
194 void to_dot_string(std::stringstream &ss) const;
195};
196
198 protected:
201
202 public:
204
205 Edge(NodePort a, NodePort b) : a_(std::move(a)), b_(std::move(b)) {}
206
208 {
209 attributes.set("arrowhead", arrowType_to_string(type));
210 }
211
213 {
214 attributes.set("arrowtail", arrowType_to_string(type));
215 }
216
218 {
219 attributes.set("dir", dirType_to_string(type));
220 }
221
223 {
224 attributes.set("label", label);
225 }
226};
227
228class DirectedEdge : public Edge {
229 public:
230 DirectedEdge(NodePort from, NodePort to) : Edge(std::move(from), std::move(to)) {}
231
232 void export__as_edge_statement(std::stringstream &ss) const;
233};
234
235class UndirectedEdge : public Edge {
236 public:
237 UndirectedEdge(NodePort a, NodePort b) : Edge(std::move(a), std::move(b)) {}
238
239 void export__as_edge_statement(std::stringstream &ss) const;
240};
241
242std::string color_attr_from_hsv(float h, float s, float v);
243
245 struct Socket {
246 std::string name;
247 std::optional<std::string> fontcolor;
248 };
249 struct Input : public Socket {};
250 struct Output : public Socket {};
251
252 std::string node_name;
255
256 Input &add_input(std::string name)
257 {
258 this->inputs.append({});
259 Input &input = this->inputs.last();
260 input.name = std::move(name);
261 return input;
262 }
263
264 Output &add_output(std::string name)
265 {
266 this->outputs.append({});
267 Output &output = this->outputs.last();
268 output.name = std::move(name);
269 return output;
270 }
271};
272
274 private:
275 Node *node_;
276
277 public:
279
281 {
282 return *node_;
283 }
284
285 NodePort input(int index) const
286 {
287 std::string port = "\"in" + std::to_string(index) + "\"";
288 return NodePort(*node_, port, "w");
289 }
290
291 NodePort output(int index) const
292 {
293 std::string port = "\"out" + std::to_string(index) + "\"";
294 return NodePort(*node_, port, "e");
295 }
296};
297
298} // namespace blender::dot_export
#define final(a, b, c)
Definition BLI_hash.h:19
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
void append(const T &value)
const T & last(const int64_t n=0) const
void set(StringRef key, float value)
void set(StringRef key, StringRef value)
void export__as_bracket_list(std::stringstream &ss) const
void set_parent_cluster(Cluster &cluster)
bool contains(Node &node) const
void set_parent_cluster(Cluster *new_parent)
Definition dot_export.cc:52
void export__declare_nodes_and_clusters(std::stringstream &ss) const
DirectedEdge(NodePort from, NodePort to)
void export__as_edge_statement(std::stringstream &ss) const
std::string to_dot_string() const
DirectedEdge & new_edge(NodePort from, NodePort to)
Definition dot_export.cc:45
void set_arrowhead(Attr_arrowType type)
void set_arrowtail(Attr_arrowType type)
void set_label(StringRef label)
void set_dir(Attr_dirType type)
Edge(NodePort a, NodePort b)
Cluster & new_cluster(StringRef label="")
Definition dot_export.cc:29
void set_rankdir(Attr_rankdir rankdir)
void export__declare_nodes_and_clusters(std::stringstream &ss) const
Node & new_node(StringRef label)
Definition dot_export.cc:20
void to_dot_string(std::stringstream &ss) const
NodePort(Node &node, std::optional< std::string > port_name={}, std::optional< std::string > port_position={})
NodeWithSocketsRef(Node &node, const NodeWithSockets &data)
void export__as_declaration(std::stringstream &ss) const
void set_shape(Attr_shape shape)
void export__as_id(std::stringstream &ss) const
void set_parent_cluster(Cluster *cluster)
Definition dot_export.cc:72
void set_parent_cluster(Cluster &cluster)
void set_background_color(StringRef name)
UndirectedEdge(NodePort a, NodePort b)
void export__as_edge_statement(std::stringstream &ss) const
UndirectedEdge & new_edge(NodePort a, NodePort b)
Definition dot_export.cc:38
#define input
#define output
StringRef dirType_to_string(Attr_dirType value)
StringRef shape_to_string(Attr_shape value)
StringRef arrowType_to_string(Attr_arrowType value)
std::string color_attr_from_hsv(float h, float s, float v)
StringRef rankdir_to_string(Attr_rankdir value)
const char * name
Input & add_input(std::string name)
Output & add_output(std::string name)