Geometry Nodes: simplify handling of invalid group interface sockets
Previously, the code tried to keep node groups working even if some of their input/output sockets had undefined type. This caused some complexity with no benefit because not all places outside of this file would handle the case correctly. Now node groups with undefined interface sockets are disabled and have to be fixed manually before they work again. Undefined interface sockets are mostly caused by invalid Python API usage and incomplete forward compatibility (e.g. when newer versions introduce new socket types that the older version does not know).
This commit is contained in:
parent
6ced6c9545
commit
3aca0bc66a
|
@ -141,6 +141,8 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
|
|||
bool has_undefined_nodes_or_sockets = false;
|
||||
bNode *group_output_node = nullptr;
|
||||
Vector<bNode *> root_frames;
|
||||
Vector<bNodeSocket *> interface_inputs;
|
||||
Vector<bNodeSocket *> interface_outputs;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -426,6 +428,18 @@ inline blender::Span<const bNode *> bNodeTree::group_input_nodes() const
|
|||
return this->nodes_by_type("NodeGroupInput");
|
||||
}
|
||||
|
||||
inline blender::Span<const bNodeSocket *> bNodeTree::interface_inputs() const
|
||||
{
|
||||
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
|
||||
return this->runtime->interface_inputs;
|
||||
}
|
||||
|
||||
inline blender::Span<const bNodeSocket *> bNodeTree::interface_outputs() const
|
||||
{
|
||||
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
|
||||
return this->runtime->interface_outputs;
|
||||
}
|
||||
|
||||
inline blender::Span<const bNodeSocket *> bNodeTree::all_input_sockets() const
|
||||
{
|
||||
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
|
||||
|
|
|
@ -42,6 +42,13 @@ static void double_checked_lock_with_task_isolation(std::mutex &mutex,
|
|||
double_checked_lock(mutex, data_is_dirty, [&]() { threading::isolate_task(fn); });
|
||||
}
|
||||
|
||||
static void update_interface_sockets(const bNodeTree &ntree)
|
||||
{
|
||||
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
|
||||
tree_runtime.interface_inputs = ntree.inputs;
|
||||
tree_runtime.interface_outputs = ntree.outputs;
|
||||
}
|
||||
|
||||
static void update_node_vector(const bNodeTree &ntree)
|
||||
{
|
||||
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
|
||||
|
@ -429,6 +436,7 @@ static void ensure_topology_cache(const bNodeTree &ntree)
|
|||
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
|
||||
double_checked_lock_with_task_isolation(
|
||||
tree_runtime.topology_cache_mutex, tree_runtime.topology_cache_is_dirty, [&]() {
|
||||
update_interface_sockets(ntree);
|
||||
update_node_vector(ntree);
|
||||
update_link_vector(ntree);
|
||||
update_socket_vectors_and_owner_node(ntree);
|
||||
|
|
|
@ -636,6 +636,9 @@ typedef struct bNodeTree {
|
|||
const bNode *group_output_node() const;
|
||||
/** Get all input nodes of the node group. */
|
||||
blender::Span<const bNode *> group_input_nodes() const;
|
||||
/** Inputs and outputs of the entire node group. */
|
||||
blender::Span<const bNodeSocket *> interface_inputs() const;
|
||||
blender::Span<const bNodeSocket *> interface_outputs() const;
|
||||
#endif
|
||||
} bNodeTree;
|
||||
|
||||
|
|
|
@ -746,20 +746,9 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||
|
||||
/**
|
||||
* All group input nodes are combined into one dummy node in the lazy-function graph.
|
||||
* If some input has an invalid type, it is ignored in the new graph. In this case null and -1 is
|
||||
* used in the vectors below.
|
||||
*/
|
||||
Vector<const CPPType *> group_input_types_;
|
||||
Vector<int> group_input_indices_;
|
||||
lf::DummyNode *group_input_lf_node_;
|
||||
|
||||
/**
|
||||
* The output types or null if an output is invalid. Each group output node gets a separate
|
||||
* corresponding dummy node in the new graph.
|
||||
*/
|
||||
Vector<const CPPType *> group_output_types_;
|
||||
Vector<int> group_output_indices_;
|
||||
|
||||
public:
|
||||
GeometryNodesLazyFunctionGraphBuilder(const bNodeTree &btree,
|
||||
GeometryNodesLazyFunctionGraphInfo &lf_graph_info)
|
||||
|
@ -776,8 +765,6 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||
conversions_ = &bke::get_implicit_type_conversions();
|
||||
|
||||
this->prepare_node_multi_functions();
|
||||
this->prepare_group_inputs();
|
||||
this->prepare_group_outputs();
|
||||
this->build_group_input_node();
|
||||
this->handle_nodes();
|
||||
this->handle_links();
|
||||
|
@ -793,50 +780,21 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||
lf_graph_info_->node_multi_functions = std::make_unique<NodeMultiFunctions>(btree_);
|
||||
}
|
||||
|
||||
void prepare_group_inputs()
|
||||
{
|
||||
LISTBASE_FOREACH (const bNodeSocket *, interface_bsocket, &btree_.inputs) {
|
||||
const CPPType *type = get_socket_cpp_type(*interface_bsocket->typeinfo);
|
||||
if (type != nullptr) {
|
||||
const int index = group_input_types_.append_and_get_index(type);
|
||||
group_input_indices_.append(index);
|
||||
}
|
||||
else {
|
||||
group_input_indices_.append(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prepare_group_outputs()
|
||||
{
|
||||
LISTBASE_FOREACH (const bNodeSocket *, interface_bsocket, &btree_.outputs) {
|
||||
const CPPType *type = get_socket_cpp_type(*interface_bsocket->typeinfo);
|
||||
if (type != nullptr) {
|
||||
const int index = group_output_types_.append_and_get_index(type);
|
||||
group_output_indices_.append(index);
|
||||
}
|
||||
else {
|
||||
group_output_indices_.append(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void build_group_input_node()
|
||||
{
|
||||
Vector<const CPPType *, 16> input_cpp_types;
|
||||
const Span<const bNodeSocket *> interface_inputs = btree_.interface_inputs();
|
||||
for (const bNodeSocket *interface_input : interface_inputs) {
|
||||
input_cpp_types.append(interface_input->typeinfo->geometry_nodes_cpp_type);
|
||||
}
|
||||
|
||||
/* Create a dummy node for the group inputs. */
|
||||
auto debug_info = std::make_unique<GroupInputDebugInfo>();
|
||||
group_input_lf_node_ = &lf_graph_->add_dummy({}, group_input_types_, debug_info.get());
|
||||
group_input_lf_node_ = &lf_graph_->add_dummy({}, input_cpp_types, debug_info.get());
|
||||
|
||||
const bNodeSocket *interface_bsocket = static_cast<bNodeSocket *>(btree_.inputs.first);
|
||||
for (const int group_input_index : group_input_indices_) {
|
||||
BLI_SCOPED_DEFER([&]() { interface_bsocket = interface_bsocket->next; });
|
||||
if (group_input_index == -1) {
|
||||
mapping_->group_input_sockets.append(nullptr);
|
||||
}
|
||||
else {
|
||||
mapping_->group_input_sockets.append(&group_input_lf_node_->output(group_input_index));
|
||||
debug_info->socket_names.append(interface_bsocket->name);
|
||||
}
|
||||
for (const int i : interface_inputs.index_range()) {
|
||||
mapping_->group_input_sockets.append(&group_input_lf_node_->output(i));
|
||||
debug_info->socket_names.append(interface_inputs[i]->name);
|
||||
}
|
||||
lf_graph_info_->dummy_debug_infos_.append(std::move(debug_info));
|
||||
}
|
||||
|
@ -946,13 +904,9 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||
|
||||
void handle_group_input_node(const bNode &bnode)
|
||||
{
|
||||
for (const int btree_index : group_input_indices_.index_range()) {
|
||||
const int lf_index = group_input_indices_[btree_index];
|
||||
if (lf_index == -1) {
|
||||
continue;
|
||||
}
|
||||
const bNodeSocket &bsocket = bnode.output_socket(btree_index);
|
||||
lf::OutputSocket &lf_socket = group_input_lf_node_->output(lf_index);
|
||||
for (const int i : btree_.interface_inputs().index_range()) {
|
||||
const bNodeSocket &bsocket = bnode.output_socket(i);
|
||||
lf::OutputSocket &lf_socket = group_input_lf_node_->output(i);
|
||||
output_socket_map_.add_new(&bsocket, &lf_socket);
|
||||
mapping_->dummy_socket_map.add_new(&bsocket, &lf_socket);
|
||||
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
|
||||
|
@ -961,23 +915,23 @@ struct GeometryNodesLazyFunctionGraphBuilder {
|
|||
|
||||
void handle_group_output_node(const bNode &bnode)
|
||||
{
|
||||
Vector<const CPPType *, 16> output_cpp_types;
|
||||
const Span<const bNodeSocket *> interface_outputs = btree_.interface_outputs();
|
||||
for (const bNodeSocket *interface_input : interface_outputs) {
|
||||
output_cpp_types.append(interface_input->typeinfo->geometry_nodes_cpp_type);
|
||||
}
|
||||
|
||||
auto debug_info = std::make_unique<GroupOutputDebugInfo>();
|
||||
lf::DummyNode &group_output_lf_node = lf_graph_->add_dummy(
|
||||
group_output_types_, {}, debug_info.get());
|
||||
output_cpp_types, {}, debug_info.get());
|
||||
|
||||
const bNodeSocket *interface_bsocket = static_cast<bNodeSocket *>(btree_.outputs.first);
|
||||
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];
|
||||
if (lf_index == -1) {
|
||||
continue;
|
||||
}
|
||||
const bNodeSocket &bsocket = bnode.input_socket(btree_index);
|
||||
lf::InputSocket &lf_socket = group_output_lf_node.input(lf_index);
|
||||
for (const int i : interface_outputs.index_range()) {
|
||||
const bNodeSocket &bsocket = bnode.input_socket(i);
|
||||
lf::InputSocket &lf_socket = group_output_lf_node.input(i);
|
||||
input_socket_map_.add(&bsocket, &lf_socket);
|
||||
mapping_->dummy_socket_map.add(&bsocket, &lf_socket);
|
||||
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
|
||||
debug_info->socket_names.append(interface_bsocket->name);
|
||||
debug_info->socket_names.append(interface_outputs[i]->name);
|
||||
}
|
||||
|
||||
lf_graph_info_->dummy_debug_infos_.append(std::move(debug_info));
|
||||
|
@ -1310,6 +1264,16 @@ const GeometryNodesLazyFunctionGraphInfo *ensure_geometry_nodes_lazy_function_gr
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (const bNodeSocket *interface_bsocket : btree.interface_inputs()) {
|
||||
if (interface_bsocket->typeinfo->geometry_nodes_cpp_type == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (const bNodeSocket *interface_bsocket : btree.interface_outputs()) {
|
||||
if (interface_bsocket->typeinfo->geometry_nodes_cpp_type == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GeometryNodesLazyFunctionGraphInfo> &lf_graph_info_ptr =
|
||||
btree.runtime->geometry_nodes_lazy_function_graph_info;
|
||||
|
|
Loading…
Reference in New Issue