From 8f362817875a9b2bcdd77e53130672624dadb2da Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 1 Mar 2024 22:36:10 +0100 Subject: [PATCH] Nodes: expose ordering of links in multi input socket in Python This fixes #116096 and is based on #115249 with some changes. This patch contains three changes: * `NodeSocket.links` in the Python API gives the links in the correct order. * `NodeLink.multi_input_sort_id` gives read-only access to an id that's used for sorting. Note that for historical reasons the highest id is the first link. * `NodeLink.swap_multi_input_sort_id(other_link)` provides a safe way to change the order of links connected to a multi-input socket. Co-authored-by: Adrian Bibby Walther Pull Request: https://projects.blender.org/blender/blender/pulls/118987 --- scripts/modules/bpy_types.py | 13 ++++-- .../blender/makesrna/intern/rna_nodetree.cc | 40 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/scripts/modules/bpy_types.py b/scripts/modules/bpy_types.py index a9562854030..0d4fd3ab3b9 100644 --- a/scripts/modules/bpy_types.py +++ b/scripts/modules/bpy_types.py @@ -1258,10 +1258,15 @@ class NodeSocket(StructRNA, metaclass=RNAMetaPropGroup): List of node links from or to this socket. .. note:: Takes ``O(len(nodetree.links))`` time.""" - return tuple( - link for link in self.id_data.links - if (link.from_socket == self or - link.to_socket == self)) + links = (link for link in self.id_data.links + if self in (link.from_socket, link.to_socket)) + + if not self.is_output: + links = sorted(links, + key=lambda link: link.multi_input_sort_id, + reverse=True) + + return tuple(links) class NodeTreeInterfaceItem(StructRNA): diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index e54a6a2405b..e203e9c0157 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -10,6 +10,8 @@ #include #include +#include + #include "BLI_function_ref.hh" #include "BLI_linear_allocator.hh" #include "BLI_math_rotation.h" @@ -1331,6 +1333,22 @@ static bool rna_NodeLink_is_hidden_get(PointerRNA *ptr) return nodeLinkIsHidden(link); } +static void rna_NodeLink_swap_multi_input_sort_id( + ID *id, bNodeLink *self, Main *bmain, ReportList *reports, bNodeLink *other) +{ + if (self->tosock != other->tosock) { + BKE_report(reports, RPT_ERROR_INVALID_INPUT, "The links must be siblings"); + return; + } + + std::swap(self->multi_input_socket_index, other->multi_input_socket_index); + + bNodeTree *ntree = reinterpret_cast(id); + BKE_ntree_update_tag_link_changed(ntree); + ED_node_tree_propagate_change(nullptr, bmain, ntree); + WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); +} + /* ******** Node ******** */ static StructRNA *rna_Node_refine(PointerRNA *ptr) @@ -10276,6 +10294,8 @@ static void rna_def_node_link(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; + PropertyRNA *parm; srna = RNA_def_struct(brna, "NodeLink", nullptr); RNA_def_struct_ui_text(srna, "NodeLink", "Link between nodes in a node tree"); @@ -10330,6 +10350,26 @@ static void rna_def_node_link(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP); RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_ui_text(prop, "Is Hidden", "Link is hidden due to invisible sockets"); + + prop = RNA_def_property(srna, "multi_input_sort_id", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, nullptr, "multi_input_socket_index"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, + "Multi Input Sort ID", + "Used to sort multiple links coming into the same input. The highest ID is at the top"); + + func = RNA_def_function( + srna, "swap_multi_input_sort_id", "rna_NodeLink_swap_multi_input_sort_id"); + RNA_def_function_ui_description( + func, "Swap the order of two links connected to the same multi-input socket"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, + "other", + "NodeLink", + "Other", + "The other link. Must link to the same multi input socket"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); } static void rna_def_nodetree_nodes_api(BlenderRNA *brna, PropertyRNA *cprop)