| 
									
										
										
										
											2025-01-22 16:18:30 +01:00
										 |  |  | import bpy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import lnx.utils | 
					
						
							|  |  |  | from lnx.logicnode.lnx_nodes import * | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CallGroupNode(LnxLogicTreeNode): | 
					
						
							|  |  |  |     """Calls the given group of nodes.""" | 
					
						
							|  |  |  |     bl_idname = 'LNCallGroupNode' | 
					
						
							|  |  |  |     bl_label = 'Call Node Group' | 
					
						
							|  |  |  |     lnx_section = 'group' | 
					
						
							|  |  |  |     lnx_version = 3 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-06 10:22:41 +00:00
										 |  |  |     def __init__(self, *args, **kwargs): | 
					
						
							|  |  |  |         super(CallGroupNode, self).__init__(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2025-01-22 16:18:30 +01:00
										 |  |  |         self.register_id() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def lnx_init(self, context): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Function to add input sockets and re-link sockets | 
					
						
							|  |  |  |     def update_inputs(self, tree, node, inp_sockets, in_links): | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  |         for output in node.outputs: | 
					
						
							|  |  |  |             _, c_socket = lnx.node_utils.output_get_connected_node(output) | 
					
						
							|  |  |  |             if c_socket is not None: | 
					
						
							|  |  |  |                 current_socket = self.add_input(c_socket.bl_idname, output.name) | 
					
						
							|  |  |  |                 if(count < len(in_links)): | 
					
						
							|  |  |  |                     # Preserve default values in input sockets | 
					
						
							|  |  |  |                     inp_sockets[count].copy_defaults(current_socket) | 
					
						
							|  |  |  |                     for link in in_links[count]: | 
					
						
							|  |  |  |                         tree.links.new(link, current_socket) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 current_socket = self.add_input('LnxAnySocket', output.name) | 
					
						
							|  |  |  |                 current_socket.display_label = output.name | 
					
						
							|  |  |  |                 if(count < len(in_links)): | 
					
						
							|  |  |  |                     for link in in_links[count]: | 
					
						
							|  |  |  |                         tree.links.new(link, current_socket) | 
					
						
							|  |  |  |             count = count + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Function to add output sockets and re-link sockets | 
					
						
							|  |  |  |     def update_outputs(self, tree, node, out_links): | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  |         for input in node.inputs: | 
					
						
							|  |  |  |             _, c_socket = lnx.node_utils.input_get_connected_node(input) | 
					
						
							|  |  |  |             if c_socket is not None: | 
					
						
							|  |  |  |                 current_socket = self.add_output(c_socket.bl_idname, input.name) | 
					
						
							|  |  |  |                 if(count < len(out_links)): | 
					
						
							|  |  |  |                     for link in out_links[count]: | 
					
						
							|  |  |  |                         nlink = tree.links.new(current_socket, link) | 
					
						
							|  |  |  |                         nlink.is_valid = True | 
					
						
							|  |  |  |                         nlink.is_muted = False | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 current_socket = self.add_output('LnxAnySocket', input.name) | 
					
						
							|  |  |  |                 current_socket.display_label = input.name | 
					
						
							|  |  |  |                 if(count < len(out_links)): | 
					
						
							|  |  |  |                     for link in out_links[count]: | 
					
						
							|  |  |  |                         tree.links.new(current_socket, link) | 
					
						
							|  |  |  |             count = count + 1 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     def remove_tree(self): | 
					
						
							|  |  |  |         self.group_tree = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update_sockets(self, context): | 
					
						
							|  |  |  |         # List to store from and to sockets of connected nodes | 
					
						
							|  |  |  |         from_socket_list = [] | 
					
						
							|  |  |  |         to_socket_list = [] | 
					
						
							|  |  |  |         inp_socket_list = [] | 
					
						
							|  |  |  |         tree = self.get_tree() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Loop through each input socket | 
					
						
							|  |  |  |         for inp in self.inputs: | 
					
						
							|  |  |  |             link_per_socket = [] | 
					
						
							|  |  |  |             #Loop through each link to the socket | 
					
						
							|  |  |  |             for link in inp.links: | 
					
						
							|  |  |  |                 link_per_socket.append(link.from_socket) | 
					
						
							|  |  |  |             from_socket_list.append(link_per_socket) | 
					
						
							|  |  |  |             inp_socket_list.append(inp) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Loop through each output socket | 
					
						
							|  |  |  |         for out in self.outputs: | 
					
						
							|  |  |  |             link_per_socket = [] | 
					
						
							|  |  |  |             # Loop through each link to the socket | 
					
						
							|  |  |  |             for link in out.links: | 
					
						
							|  |  |  |                 link_per_socket.append(link.to_socket) | 
					
						
							|  |  |  |             to_socket_list.append(link_per_socket) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Remove all output sockets | 
					
						
							|  |  |  |         for output in self.outputs: | 
					
						
							|  |  |  |             self.outputs.remove(output) | 
					
						
							|  |  |  |         # Search for Group Input/Output | 
					
						
							|  |  |  |         if self.group_tree is not None: | 
					
						
							|  |  |  |             for node in self.group_tree.nodes: | 
					
						
							|  |  |  |                 if node.bl_idname == 'LNGroupInputsNode': | 
					
						
							|  |  |  |                     # Update input sockets | 
					
						
							|  |  |  |                     self.update_inputs(tree, node, inp_socket_list, from_socket_list) | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |             for node in self.group_tree.nodes: | 
					
						
							|  |  |  |                 if node.bl_idname == 'LNGroupOutputsNode': | 
					
						
							|  |  |  |                     # Update output sockets | 
					
						
							|  |  |  |                     self.update_outputs(tree, node, to_socket_list) | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |         #Remove all old input sockets after setting defaults | 
					
						
							|  |  |  |         for inp in inp_socket_list: | 
					
						
							|  |  |  |             self.inputs.remove(inp) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Prperty to store group tree pointer | 
					
						
							|  |  |  |     group_tree: PointerProperty(name='Group', type=bpy.types.NodeTree, update=update_sockets) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def draw_label(self) -> str: | 
					
						
							|  |  |  |         if self.group_tree is not None: | 
					
						
							|  |  |  |             return f'Group: {self.group_tree.name}' | 
					
						
							|  |  |  |         return self.bl_label | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Draw node UI | 
					
						
							|  |  |  |     def draw_buttons(self, context, layout): | 
					
						
							|  |  |  |         col = layout.column() | 
					
						
							|  |  |  |         row_name = col.row(align=True) | 
					
						
							|  |  |  |         row_add = col.row(align=True) | 
					
						
							|  |  |  |         row_ops = col.row() | 
					
						
							|  |  |  |         if self.group_tree is None: | 
					
						
							|  |  |  |             op = row_add.operator('lnx.add_group_tree', icon='PLUS', text='New Group') | 
					
						
							|  |  |  |             op.node_index = self.get_id_str() | 
					
						
							|  |  |  |         op = row_name.operator('lnx.search_group_tree', text='', icon='VIEWZOOM') | 
					
						
							|  |  |  |         op.node_index = self.get_id_str() | 
					
						
							|  |  |  |         if self.group_tree: | 
					
						
							|  |  |  |             row_name.prop(self.group_tree, 'name', text='') | 
					
						
							|  |  |  |             row_copy = row_name.split(align=True) | 
					
						
							|  |  |  |             row_copy.alignment = 'CENTER' | 
					
						
							|  |  |  |             fake_user = 1 if self.group_tree.use_fake_user else 0 | 
					
						
							|  |  |  |             op = row_copy.operator('lnx.copy_group_tree', text=str(self.group_tree.users - fake_user)) | 
					
						
							|  |  |  |             op.node_index = self.get_id_str() | 
					
						
							|  |  |  |             row_name.prop(self.group_tree, 'use_fake_user', text='') | 
					
						
							|  |  |  |             op = row_name.operator('lnx.unlink_group_tree', icon='X', text='') | 
					
						
							|  |  |  |             op.node_index = self.get_id_str() | 
					
						
							|  |  |  |         row_ops.enabled = not self.group_tree is None | 
					
						
							|  |  |  |         op = row_ops.operator('lnx.edit_group_tree', icon='FULLSCREEN_ENTER', text='Edit tree') | 
					
						
							|  |  |  |         op.node_index = self.get_id_str() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_replacement_node(self, node_tree: bpy.types.NodeTree): | 
					
						
							|  |  |  |         if self.lnx_version not in (0, 1, 2): | 
					
						
							|  |  |  |             raise LookupError() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return node_tree.nodes.new('LNCallGroupNode') |