Geometry Nodes: improve dot graph export of lazy function graph
* Dim default input values. * Print default input values instead of type name. * Add node/socket names to group input/output nodes.
This commit is contained in:
@@ -38,7 +38,7 @@ inline ValueOrFieldCPPType::ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*
|
|||||||
* Create a new #ValueOrFieldCPPType that can be accessed through `ValueOrFieldCPPType::get<T>()`.
|
* Create a new #ValueOrFieldCPPType that can be accessed through `ValueOrFieldCPPType::get<T>()`.
|
||||||
*/
|
*/
|
||||||
#define FN_FIELD_CPP_TYPE_MAKE(VALUE_TYPE) \
|
#define FN_FIELD_CPP_TYPE_MAKE(VALUE_TYPE) \
|
||||||
BLI_CPP_TYPE_MAKE(blender::fn::ValueOrField<VALUE_TYPE>, CPPTypeFlags::None) \
|
BLI_CPP_TYPE_MAKE(blender::fn::ValueOrField<VALUE_TYPE>, CPPTypeFlags::Printable) \
|
||||||
template<> \
|
template<> \
|
||||||
const blender::fn::ValueOrFieldCPPType & \
|
const blender::fn::ValueOrFieldCPPType & \
|
||||||
blender::fn::ValueOrFieldCPPType::get_impl<VALUE_TYPE>() \
|
blender::fn::ValueOrFieldCPPType::get_impl<VALUE_TYPE>() \
|
||||||
|
|||||||
@@ -167,15 +167,25 @@ class FunctionNode : public Node {
|
|||||||
const LazyFunction &function() const;
|
const LazyFunction &function() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DummyDebugInfo {
|
||||||
|
public:
|
||||||
|
virtual ~DummyDebugInfo() = default;
|
||||||
|
virtual std::string node_name() const;
|
||||||
|
virtual std::string input_name(const int i) const;
|
||||||
|
virtual std::string output_name(const int i) const;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A #Node that does *not* correspond to a #LazyFunction. Instead it can be used to indicate inputs
|
* A #Node that does *not* correspond to a #LazyFunction. Instead it can be used to indicate inputs
|
||||||
* and outputs of the entire graph. It can have an arbitrary number of inputs and outputs.
|
* and outputs of the entire graph. It can have an arbitrary number of inputs and outputs.
|
||||||
*/
|
*/
|
||||||
class DummyNode : public Node {
|
class DummyNode : public Node {
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
const DummyDebugInfo *debug_info_ = nullptr;
|
||||||
|
|
||||||
friend Node;
|
friend Node;
|
||||||
|
friend Socket;
|
||||||
|
friend Graph;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,7 +218,9 @@ class Graph : NonCopyable, NonMovable {
|
|||||||
/**
|
/**
|
||||||
* Add a new dummy node with the given socket types.
|
* Add a new dummy node with the given socket types.
|
||||||
*/
|
*/
|
||||||
DummyNode &add_dummy(Span<const CPPType *> input_types, Span<const CPPType *> output_types);
|
DummyNode &add_dummy(Span<const CPPType *> input_types,
|
||||||
|
Span<const CPPType *> output_types,
|
||||||
|
const DummyDebugInfo *debug_info = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a link between the two given sockets.
|
* Add a link between the two given sockets.
|
||||||
|
|||||||
@@ -48,13 +48,16 @@ FunctionNode &Graph::add_function(const LazyFunction &fn)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
DummyNode &Graph::add_dummy(Span<const CPPType *> input_types, Span<const CPPType *> output_types)
|
DummyNode &Graph::add_dummy(Span<const CPPType *> input_types,
|
||||||
|
Span<const CPPType *> output_types,
|
||||||
|
const DummyDebugInfo *debug_info)
|
||||||
{
|
{
|
||||||
DummyNode &node = *allocator_.construct<DummyNode>().release();
|
DummyNode &node = *allocator_.construct<DummyNode>().release();
|
||||||
node.fn_ = nullptr;
|
node.fn_ = nullptr;
|
||||||
node.inputs_ = allocator_.construct_elements_and_pointer_array<InputSocket>(input_types.size());
|
node.inputs_ = allocator_.construct_elements_and_pointer_array<InputSocket>(input_types.size());
|
||||||
node.outputs_ = allocator_.construct_elements_and_pointer_array<OutputSocket>(
|
node.outputs_ = allocator_.construct_elements_and_pointer_array<OutputSocket>(
|
||||||
output_types.size());
|
output_types.size());
|
||||||
|
node.debug_info_ = debug_info;
|
||||||
|
|
||||||
for (const int i : input_types.index_range()) {
|
for (const int i : input_types.index_range()) {
|
||||||
InputSocket &socket = *node.inputs_[i];
|
InputSocket &socket = *node.inputs_[i];
|
||||||
@@ -100,6 +103,8 @@ bool Graph::node_indices_are_valid() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *fallback_name = "No Name";
|
||||||
|
|
||||||
std::string Socket::name() const
|
std::string Socket::name() const
|
||||||
{
|
{
|
||||||
if (node_->is_function()) {
|
if (node_->is_function()) {
|
||||||
@@ -110,16 +115,42 @@ std::string Socket::name() const
|
|||||||
}
|
}
|
||||||
return fn.output_name(index_in_node_);
|
return fn.output_name(index_in_node_);
|
||||||
}
|
}
|
||||||
return "Unnamed";
|
const DummyNode &dummy_node = *static_cast<const DummyNode *>(node_);
|
||||||
|
if (dummy_node.debug_info_) {
|
||||||
|
if (is_input_) {
|
||||||
|
return dummy_node.debug_info_->input_name(index_in_node_);
|
||||||
|
}
|
||||||
|
return dummy_node.debug_info_->output_name(index_in_node_);
|
||||||
|
}
|
||||||
|
return fallback_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Node::name() const
|
std::string Node::name() const
|
||||||
{
|
{
|
||||||
if (fn_ == nullptr) {
|
if (this->is_function()) {
|
||||||
return static_cast<const DummyNode *>(this)->name_;
|
|
||||||
}
|
|
||||||
return fn_->name();
|
return fn_->name();
|
||||||
}
|
}
|
||||||
|
const DummyNode &dummy_node = *static_cast<const DummyNode *>(this);
|
||||||
|
if (dummy_node.debug_info_) {
|
||||||
|
return dummy_node.debug_info_->node_name();
|
||||||
|
}
|
||||||
|
return fallback_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DummyDebugInfo::node_name() const
|
||||||
|
{
|
||||||
|
return fallback_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DummyDebugInfo::input_name(const int /*i*/) const
|
||||||
|
{
|
||||||
|
return fallback_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DummyDebugInfo::output_name(const int /*i*/) const
|
||||||
|
{
|
||||||
|
return fallback_name;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Graph::to_dot() const
|
std::string Graph::to_dot() const
|
||||||
{
|
{
|
||||||
@@ -166,10 +197,11 @@ std::string Graph::to_dot() const
|
|||||||
value_string = type.to_string(default_value);
|
value_string = type.to_string(default_value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value_string = "<" + type.name() + ">";
|
value_string = type.name();
|
||||||
}
|
}
|
||||||
dot::Node &default_value_dot_node = digraph.new_node(value_string);
|
dot::Node &default_value_dot_node = digraph.new_node(value_string);
|
||||||
default_value_dot_node.set_shape(dot::Attr_shape::Ellipse);
|
default_value_dot_node.set_shape(dot::Attr_shape::Ellipse);
|
||||||
|
default_value_dot_node.attributes.set("color", "#00000055");
|
||||||
digraph.new_edge(default_value_dot_node, to_dot_port);
|
digraph.new_edge(default_value_dot_node, to_dot_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ struct GeometryNodesLazyFunctionGraphInfo {
|
|||||||
* we have to keep track of them separately.
|
* we have to keep track of them separately.
|
||||||
*/
|
*/
|
||||||
Vector<std::unique_ptr<LazyFunction>> functions;
|
Vector<std::unique_ptr<LazyFunction>> functions;
|
||||||
|
/**
|
||||||
|
* Debug info that has to be destructed when the graph is not used anymore.
|
||||||
|
*/
|
||||||
|
Vector<std::unique_ptr<lf::DummyDebugInfo>> dummy_debug_infos_;
|
||||||
/**
|
/**
|
||||||
* Many sockets have default values. Since those are not owned by the lazy-function graph, we
|
* Many sockets have default values. Since those are not owned by the lazy-function graph, we
|
||||||
* have to keep track of them separately. This only owns the values, the memory is owned by the
|
* have to keep track of them separately. This only owns the values, the memory is owned by the
|
||||||
|
|||||||
@@ -698,6 +698,36 @@ static GMutablePointer get_socket_default_value(LinearAllocator<> &allocator,
|
|||||||
return {type, buffer};
|
return {type, buffer};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GroupInputDebugInfo : public lf::DummyDebugInfo {
|
||||||
|
public:
|
||||||
|
Vector<StringRef> socket_names;
|
||||||
|
|
||||||
|
std::string node_name() const override
|
||||||
|
{
|
||||||
|
return "Group Input";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string output_name(const int i) const override
|
||||||
|
{
|
||||||
|
return this->socket_names[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GroupOutputDebugInfo : public lf::DummyDebugInfo {
|
||||||
|
public:
|
||||||
|
Vector<StringRef> socket_names;
|
||||||
|
|
||||||
|
std::string node_name() const
|
||||||
|
{
|
||||||
|
return "Group Output";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_name(const int i) const override
|
||||||
|
{
|
||||||
|
return this->socket_names[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to build a lazy-function graph based on a geometry nodes tree.
|
* Utility class to build a lazy-function graph based on a geometry nodes tree.
|
||||||
* This is mainly a separate class because it makes it easier to have variables that can be
|
* This is mainly a separate class because it makes it easier to have variables that can be
|
||||||
@@ -794,15 +824,21 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||||||
void build_group_input_node()
|
void build_group_input_node()
|
||||||
{
|
{
|
||||||
/* Create a dummy node for the group inputs. */
|
/* Create a dummy node for the group inputs. */
|
||||||
group_input_lf_node_ = &lf_graph_->add_dummy({}, group_input_types_);
|
auto debug_info = std::make_unique<GroupInputDebugInfo>();
|
||||||
|
group_input_lf_node_ = &lf_graph_->add_dummy({}, group_input_types_, debug_info.get());
|
||||||
|
|
||||||
|
const bNodeSocket *interface_bsocket = static_cast<bNodeSocket *>(btree_.inputs.first);
|
||||||
for (const int group_input_index : group_input_indices_) {
|
for (const int group_input_index : group_input_indices_) {
|
||||||
|
BLI_SCOPED_DEFER([&]() { interface_bsocket = interface_bsocket->next; });
|
||||||
if (group_input_index == -1) {
|
if (group_input_index == -1) {
|
||||||
mapping_->group_input_sockets.append(nullptr);
|
mapping_->group_input_sockets.append(nullptr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mapping_->group_input_sockets.append(&group_input_lf_node_->output(group_input_index));
|
mapping_->group_input_sockets.append(&group_input_lf_node_->output(group_input_index));
|
||||||
|
debug_info->socket_names.append(interface_bsocket->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lf_graph_info_->dummy_debug_infos_.append(std::move(debug_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_nodes()
|
void handle_nodes()
|
||||||
@@ -925,8 +961,13 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||||||
|
|
||||||
void handle_group_output_node(const bNode &bnode)
|
void handle_group_output_node(const bNode &bnode)
|
||||||
{
|
{
|
||||||
lf::DummyNode &group_output_lf_node = lf_graph_->add_dummy(group_output_types_, {});
|
auto debug_info = std::make_unique<GroupOutputDebugInfo>();
|
||||||
|
lf::DummyNode &group_output_lf_node = lf_graph_->add_dummy(
|
||||||
|
group_output_types_, {}, debug_info.get());
|
||||||
|
|
||||||
|
const bNodeSocket *interface_bsocket = static_cast<bNodeSocket *>(btree_.outputs.first);
|
||||||
for (const int btree_index : group_output_indices_.index_range()) {
|
for (const int btree_index : group_output_indices_.index_range()) {
|
||||||
|
BLI_SCOPED_DEFER([&]() { interface_bsocket = interface_bsocket->next; });
|
||||||
const int lf_index = group_output_indices_[btree_index];
|
const int lf_index = group_output_indices_[btree_index];
|
||||||
if (lf_index == -1) {
|
if (lf_index == -1) {
|
||||||
continue;
|
continue;
|
||||||
@@ -936,7 +977,10 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||||||
input_socket_map_.add(&bsocket, &lf_socket);
|
input_socket_map_.add(&bsocket, &lf_socket);
|
||||||
mapping_->dummy_socket_map.add(&bsocket, &lf_socket);
|
mapping_->dummy_socket_map.add(&bsocket, &lf_socket);
|
||||||
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
|
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
|
||||||
|
debug_info->socket_names.append(interface_bsocket->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lf_graph_info_->dummy_debug_infos_.append(std::move(debug_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_group_node(const bNode &bnode)
|
void handle_group_node(const bNode &bnode)
|
||||||
|
|||||||
Reference in New Issue
Block a user