forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			558 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			558 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import bpy
 | |
| from bpy.props import *
 | |
| 
 | |
| import lnx.log
 | |
| import lnx.make_state
 | |
| import lnx.node_utils
 | |
| import lnx.props_traits_props
 | |
| import lnx.utils
 | |
| import lnx.logicnode.lnx_nodes
 | |
| 
 | |
| if lnx.is_reload(__name__):
 | |
|     lnx.log = lnx.reload_module(lnx.log)
 | |
|     lnx.make_state = lnx.reload_module(lnx.make_state)
 | |
|     lnx.node_utils = lnx.reload_module(lnx.node_utils)
 | |
|     lnx.props_traits_props = lnx.reload_module(lnx.props_traits_props)
 | |
|     lnx.utils = lnx.reload_module(lnx.utils)
 | |
|     lnx.logicnode.lnx_nodes = lnx.reload_module(lnx.logicnode.lnx_nodes)
 | |
| else:
 | |
|     lnx.enable_reload(__name__)
 | |
| 
 | |
| 
 | |
| class LNX_PT_Variables(bpy.types.Panel):
 | |
|     bl_label = 'Tree Variables'
 | |
|     bl_idname = 'LNX_PT_Variables'
 | |
|     bl_space_type = 'NODE_EDITOR'
 | |
|     bl_region_type = 'UI'
 | |
|     bl_category = 'Leenkx'
 | |
| 
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|         return context.space_data.tree_type == 'LnxLogicTreeType' and context.space_data.edit_tree
 | |
| 
 | |
|     def draw(self, context):
 | |
|         layout = self.layout
 | |
| 
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         node = context.active_node
 | |
|         if node is None or node.lnx_logic_id == '':
 | |
|             layout.operator('lnx.variable_promote_node', icon='PLUS')
 | |
|         else:
 | |
|             layout.operator('lnx.variable_node_make_local', icon='TRIA_DOWN_BAR')
 | |
| 
 | |
|         row = layout.row(align=True)
 | |
|         col = row.column(align=True)
 | |
| 
 | |
|         num_prop_rows = max(len(tree.lnx_treevariableslist), 6)
 | |
|         col.template_list('LNX_UL_TreeVarList', '', tree, 'lnx_treevariableslist', tree, 'lnx_treevariableslist_index', rows=num_prop_rows)
 | |
| 
 | |
|         col.operator('lnx.variable_assign_to_node', icon='NODE')
 | |
| 
 | |
|         if len(tree.lnx_treevariableslist) > 0:
 | |
|             selected_item = tree.lnx_treevariableslist[tree.lnx_treevariableslist_index]
 | |
| 
 | |
|             col.separator()
 | |
|             sub_row = col.row(align=True)
 | |
|             sub_row.alignment = 'EXPAND'
 | |
|             op = sub_row.operator('lnx.add_var_node')
 | |
|             op.node_id = selected_item.name
 | |
|             op.node_type = selected_item.node_type
 | |
|             op = sub_row.operator('lnx.add_setvar_node')
 | |
|             op.node_id = selected_item.name
 | |
|             op.node_type = selected_item.node_type
 | |
| 
 | |
|         col = row.column(align=True)
 | |
|         col.enabled = len(tree.lnx_treevariableslist) > 1
 | |
|         col.operator('lnx_treevariableslist.move_item', icon='TRIA_UP', text='').direction = 'UP'
 | |
|         col.operator('lnx_treevariableslist.move_item', icon='TRIA_DOWN', text='').direction = 'DOWN'
 | |
| 
 | |
|         if len(tree.lnx_treevariableslist) > 0:
 | |
|             selected_item = tree.lnx_treevariableslist[tree.lnx_treevariableslist_index]
 | |
| 
 | |
|             box = layout.box()
 | |
|             box.label(text='Selected Variable:')
 | |
|             master_node = lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin.get_master_node(tree, selected_item.name)
 | |
|             master_node.draw_content(context, box)
 | |
|             for inp in master_node.inputs:
 | |
|                 if hasattr(inp, 'draw'):
 | |
|                     inp.draw(context, box, master_node, inp.label if inp.label is not None else inp.name)
 | |
| 
 | |
| 
 | |
| class LNX_OT_TreeVariablePromoteNode(bpy.types.Operator):
 | |
|     bl_idname = 'lnx.variable_promote_node'
 | |
|     bl_label = 'New Var From Node'
 | |
|     bl_description = 'Create a tree variable from the active node and promote it to a tree variable node'
 | |
| 
 | |
|     var_name: StringProperty(
 | |
|         name='Name',
 | |
|         description='Name of the new tree variable',
 | |
|         default='Untitled'
 | |
|     )
 | |
| 
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|         if not lnx.logicnode.lnx_nodes.is_logic_node_edit_context(context):
 | |
|             return False
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         if tree is None:
 | |
|             return False
 | |
| 
 | |
|         node = context.active_node
 | |
|         if node is None or not node.bl_idname.startswith('LN'):
 | |
|             return False
 | |
| 
 | |
|         if not isinstance(node, lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin):
 | |
|             return False
 | |
| 
 | |
|         return node.lnx_logic_id == ''
 | |
| 
 | |
|     def invoke(self, context, event):
 | |
|         wm = context.window_manager
 | |
|         return wm.invoke_props_dialog(self, width=400)
 | |
| 
 | |
|     def execute(self, context):
 | |
|         node: lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin = context.active_node
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
| 
 | |
|         var_type = node.bl_idname
 | |
|         var_item = LNX_PG_TreeVarListItem.create_new(tree, self.var_name, var_type)
 | |
| 
 | |
|         node.is_master_node = True
 | |
|         node.lnx_logic_id = var_item.name
 | |
|         node.use_custom_color = True
 | |
|         node.color = var_item.color
 | |
| 
 | |
|         lnx.make_state.redraw_ui = True
 | |
| 
 | |
|         return {'FINISHED'}
 | |
| 
 | |
|     def draw(self, context):
 | |
|         layout = self.layout
 | |
|         row = layout.row()
 | |
|         row.scale_y = 1.3
 | |
|         row.activate_init = True
 | |
|         row.prop(self, 'var_name')
 | |
| 
 | |
| 
 | |
| class LNX_OT_TreeVariableMakeLocalNode(bpy.types.Operator):
 | |
|     bl_idname = 'lnx.variable_node_make_local'
 | |
|     bl_label = 'Make Node Local'
 | |
|     bl_description = (
 | |
|         'Remove the reference to the tree variable from the active node. '
 | |
|         'If the active node is the only node that links to the selected '
 | |
|         'tree variable, the tree variable is removed'
 | |
|     )
 | |
| 
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|         if not lnx.logicnode.lnx_nodes.is_logic_node_edit_context(context):
 | |
|             return False
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         if tree is None:
 | |
|             return False
 | |
| 
 | |
|         node = context.active_node
 | |
|         if node is None or not node.bl_idname.startswith('LN'):
 | |
|             return False
 | |
| 
 | |
|         if not isinstance(node, lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin):
 | |
|             return False
 | |
| 
 | |
|         return node.lnx_logic_id != ''
 | |
| 
 | |
|     def execute(self, context):
 | |
|         node: lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin = context.active_node
 | |
|         node.make_local()
 | |
|         node.color = [0.608, 0.608, 0.608]  # default color
 | |
|         node.use_custom_color = False
 | |
| 
 | |
|         return {'FINISHED'}
 | |
| 
 | |
| 
 | |
| class LNX_OT_TreeVariableVariableAssignToNode(bpy.types.Operator):
 | |
|     bl_idname = 'lnx.variable_assign_to_node'
 | |
|     bl_label = 'Assign To Node'
 | |
|     bl_description = (
 | |
|             'Assign the selected tree variable to the active variable node. '
 | |
|             'The variable node must have the same type as the variable'
 | |
|     )
 | |
| 
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|         if not lnx.logicnode.lnx_nodes.is_logic_node_edit_context(context):
 | |
|             return False
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         if tree is None or len(tree.lnx_treevariableslist) == 0:
 | |
|             return False
 | |
| 
 | |
|         node = context.active_node
 | |
|         if node is None or not node.bl_idname.startswith('LN'):
 | |
|             return False
 | |
| 
 | |
|         if not isinstance(node, lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin):
 | |
|             return False
 | |
| 
 | |
|         # Only assign variables to nodes of the correct type
 | |
|         if node.bl_idname != tree.lnx_treevariableslist[tree.lnx_treevariableslist_index].node_type:
 | |
|             return False
 | |
| 
 | |
|         return True
 | |
| 
 | |
|     def execute(self, context):
 | |
|         node: lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin = context.active_node
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
| 
 | |
|         var_item = tree.lnx_treevariableslist[tree.lnx_treevariableslist_index]
 | |
| 
 | |
|         # Make node local first to ensure the old tree variable (if
 | |
|         # linked) is notified that the node is no longer linked
 | |
|         if node.lnx_logic_id != var_item.name:
 | |
|             node.make_local()
 | |
| 
 | |
|         node.lnx_logic_id = var_item.name
 | |
|         node.use_custom_color = True
 | |
|         node.color = var_item.color
 | |
|         lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin.synchronize(tree, node.lnx_logic_id)
 | |
| 
 | |
|         return {'FINISHED'}
 | |
| 
 | |
| 
 | |
| class LNX_OT_TreeVariableListMoveItem(bpy.types.Operator):
 | |
|     bl_idname = 'lnx_treevariableslist.move_item'
 | |
|     bl_label = 'Move'
 | |
|     bl_description = 'Move an item in the list'
 | |
|     bl_options = {'UNDO', 'INTERNAL'}
 | |
| 
 | |
|     direction: EnumProperty(
 | |
|         items=(
 | |
|             ('UP', 'Up', ''),
 | |
|             ('DOWN', 'Down', '')
 | |
|         )
 | |
|     )
 | |
| 
 | |
|     def execute(self, context):
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         index = tree.lnx_treevariableslist_index
 | |
| 
 | |
|         max_index = len(tree.lnx_treevariableslist) - 1
 | |
|         new_index = 0
 | |
| 
 | |
|         if self.direction == 'UP':
 | |
|             new_index = index - 1
 | |
|         elif self.direction == 'DOWN':
 | |
|             new_index = index + 1
 | |
|         new_index = max(0, min(new_index, max_index))
 | |
| 
 | |
|         tree.lnx_treevariableslist.move(index, new_index)
 | |
|         tree.lnx_treevariableslist_index = new_index
 | |
| 
 | |
|         return{'FINISHED'}
 | |
| 
 | |
| 
 | |
| class LNX_OT_AddVarGetterNode(bpy.types.Operator):
 | |
|     """Add a node to get the value of the selected tree variable"""
 | |
|     bl_idname = 'lnx.add_var_node'
 | |
|     bl_label = 'Add Getter'
 | |
|     bl_options = {'GRAB_CURSOR', 'BLOCKING'}
 | |
| 
 | |
|     node_id: StringProperty()
 | |
|     node_type: StringProperty()
 | |
|     getter_node_ref = None
 | |
| 
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|         if not lnx.logicnode.lnx_nodes.is_logic_node_edit_context(context):
 | |
|             return False
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         return tree is not None and len(tree.lnx_treevariableslist) > 0
 | |
| 
 | |
|     def invoke(self, context, event):
 | |
|         context.window_manager.modal_handler_add(self)
 | |
|         self.execute(context)
 | |
|         return {'RUNNING_MODAL'}
 | |
| 
 | |
|     def modal(self, context, event):
 | |
|         if event.type == 'MOUSEMOVE':
 | |
|             self.getter_node_ref.location = context.space_data.cursor_location
 | |
|         elif event.type == 'LEFTMOUSE':  # Confirm
 | |
|             return {'FINISHED'}
 | |
|         return {'RUNNING_MODAL'}
 | |
| 
 | |
|     def execute(self, context):
 | |
|         self.getter_node_ref = self.create_getter_node(context, self.node_type, self.node_id)
 | |
|         return {'FINISHED'}
 | |
| 
 | |
|     @staticmethod
 | |
|     def create_getter_node(context, node_type: str, node_id: str) -> lnx.logicnode.lnx_nodes.LnxLogicTreeNode:
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         nodes = context.space_data.path[-1].node_tree.nodes
 | |
| 
 | |
|         node = nodes.new(node_type)
 | |
|         node.location = context.space_data.cursor_location
 | |
|         node.lnx_logic_id = node_id
 | |
|         node.use_custom_color = True
 | |
|         node.color = tree.lnx_treevariableslist[tree.lnx_treevariableslist_index].color
 | |
| 
 | |
|         lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin.synchronize(tree, node.lnx_logic_id)
 | |
| 
 | |
|         return node
 | |
| 
 | |
| 
 | |
| class LNX_OT_AddVarSetterNode(bpy.types.Operator):
 | |
|     """Add a node to set the value of the selected tree variable"""
 | |
|     bl_idname = 'lnx.add_setvar_node'
 | |
|     bl_label = 'Add Setter'
 | |
|     bl_options = {'GRAB_CURSOR', 'BLOCKING'}
 | |
| 
 | |
|     node_id: StringProperty()
 | |
|     node_type: StringProperty()
 | |
|     getter_node_ref = None
 | |
|     setter_node_ref = None
 | |
| 
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|         if not lnx.logicnode.lnx_nodes.is_logic_node_edit_context(context):
 | |
|             return False
 | |
|         tree: bpy.types.NodeTree = context.space_data.path[-1].node_tree
 | |
|         return tree is not None and len(tree.lnx_treevariableslist) > 0
 | |
| 
 | |
|     def invoke(self, context, event):
 | |
|         context.window_manager.modal_handler_add(self)
 | |
|         self.execute(context)
 | |
|         return {'RUNNING_MODAL'}
 | |
| 
 | |
|     def modal(self, context, event):
 | |
|         if event.type == 'MOUSEMOVE':
 | |
|             self.setter_node_ref.location = context.space_data.cursor_location
 | |
|             self.getter_node_ref.location[0] = context.space_data.cursor_location[0]
 | |
|             self.getter_node_ref.location[1] = context.space_data.cursor_location[1] - self.setter_node_ref.height - 17
 | |
|         elif event.type == 'LEFTMOUSE':  # Confirm
 | |
|             return {'FINISHED'}
 | |
|         return {'RUNNING_MODAL'}
 | |
| 
 | |
|     def execute(self, context):
 | |
|         nodes = context.space_data.path[-1].node_tree.nodes
 | |
| 
 | |
|         node = LNX_OT_AddVarGetterNode.create_getter_node(context, self.node_type, self.node_id)
 | |
| 
 | |
|         setter_node = nodes.new('LNSetVariableNode')
 | |
|         setter_node.location = context.space_data.cursor_location
 | |
| 
 | |
|         links = context.space_data.path[-1].node_tree.links
 | |
|         links.new(node.outputs[0], setter_node.inputs[1])
 | |
| 
 | |
|         self.getter_node_ref = node
 | |
|         self.setter_node_ref = setter_node
 | |
|         return {'FINISHED'}
 | |
| 
 | |
| 
 | |
| class LNX_PG_TreeVarListItem(bpy.types.PropertyGroup):
 | |
|     def _set_name(self, value: str):
 | |
|         old_name = self._get_name()
 | |
| 
 | |
|         tree = bpy.context.space_data.path[-1].node_tree
 | |
|         lst = tree.lnx_treevariableslist
 | |
| 
 | |
|         if value == '':
 | |
|             # Don't allow empty variable names
 | |
|             new_name = old_name
 | |
|         else:
 | |
|             new_name = lnx.utils.unique_name_in_lists(item_lists=[lst], name_attr='name', wanted_name=value, ignore_item=self)
 | |
| 
 | |
|         self['_name'] = new_name
 | |
| 
 | |
|         for node in tree.nodes:
 | |
|             if node.lnx_logic_id == old_name:
 | |
|                 node.lnx_logic_id = new_name
 | |
| 
 | |
|     def _get_name(self) -> str:
 | |
|         return self.get('_name', 'Untitled')
 | |
| 
 | |
|     def _update_color(self, context):
 | |
|         space = context.space_data
 | |
| 
 | |
|         # Can be None if color is set before tree is initialized (upon
 | |
|         # updating old files to newer SDK for example)
 | |
|         if space is not None:
 | |
|             for node in space.path[-1].node_tree.nodes:
 | |
|                 if node.lnx_logic_id == self.name:
 | |
|                     node.use_custom_color = True
 | |
|                     node.color = self.color
 | |
| 
 | |
|     name: StringProperty(
 | |
|         name='Name',
 | |
|         description='The name of this variable',
 | |
|         default='Untitled',
 | |
|         get=_get_name,
 | |
|         set=_set_name
 | |
|     )
 | |
| 
 | |
|     node_type: StringProperty(
 | |
|         name='Type',
 | |
|         description='The type of this variable/the bl_idname of the node\'s that may use this variable',
 | |
|         default='LNIntegerNode'
 | |
|     )
 | |
| 
 | |
|     color: FloatVectorProperty(
 | |
|         name='Color',
 | |
|         description='The color of the nodes that link to this tree variable',
 | |
|         subtype='COLOR',
 | |
|         default=[1.0, 1.0, 1.0],
 | |
|         update=_update_color,
 | |
|         size=3,
 | |
|         min=0,
 | |
|         max=1
 | |
|     )
 | |
| 
 | |
|     @classmethod
 | |
|     def create_new(cls, tree: bpy.types.NodeTree, item_name: str, item_type: str) -> 'LNX_PG_TreeVarListItem':
 | |
|         lst = tree.lnx_treevariableslist
 | |
| 
 | |
|         var_item: LNX_PG_TreeVarListItem = lst.add()
 | |
|         var_item['_name'] = lnx.utils.unique_name_in_lists(
 | |
|             item_lists=[lst], name_attr='name', wanted_name=item_name, ignore_item=var_item
 | |
|         )
 | |
|         var_item.node_type = item_type
 | |
|         var_item.color = lnx.utils.get_random_color_rgb()
 | |
| 
 | |
|         tree.lnx_treevariableslist_index = len(lst) - 1
 | |
|         lnx.make_state.redraw_ui = True
 | |
| 
 | |
|         return var_item
 | |
| 
 | |
| 
 | |
| class LNX_UL_TreeVarList(bpy.types.UIList):
 | |
|     def draw_item(self, context, layout, data, item: LNX_PG_TreeVarListItem, icon, active_data, active_propname, index):
 | |
|         node_type = lnx.utils.type_name_to_type(item.node_type).bl_label
 | |
| 
 | |
|         row = layout.row(align=True)
 | |
|         _row = row.row()
 | |
|         _row.ui_units_x = 1.0
 | |
|         _row.prop(item, 'color', text='')
 | |
|         row.prop(item, 'name', text='', emboss=False)
 | |
|         row.label(text=node_type)
 | |
| 
 | |
| 
 | |
| def on_update_node_logic_id(node: lnx.logicnode.lnx_nodes.LnxLogicTreeNode, context):
 | |
|     node.on_logic_id_change()
 | |
| 
 | |
| 
 | |
| def node_compat_sdk2203():
 | |
|     """Replace old lnx_logic_id system with tree variable system."""
 | |
|     for tree in bpy.data.node_groups:
 | |
|         if tree.bl_idname == 'LnxLogicTreeType':
 | |
|             # All tree variable nodes
 | |
|             tv_nodes: dict[str, list[lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin]] = {}
 | |
| 
 | |
|             # The type of the tree variable. If two types are found for
 | |
|             # a logic ID and one is dynamic, assume it's a getter node.
 | |
|             # Otherwise show a warning upon conflict, it was undefined
 | |
|             # behaviour before anyway.
 | |
|             tv_types: dict[str, str] = {}
 | |
| 
 | |
|             # First pass: find all tree variable nodes and decide the
 | |
|             # variable type in case of conflicts
 | |
|             node: lnx.logicnode.lnx_nodes.LnxLogicTreeNode
 | |
|             for node in list(tree.nodes):
 | |
|                 if node.lnx_logic_id != '':
 | |
|                     if not isinstance(node, lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin):
 | |
|                         lnx.log.warn(
 | |
|                             'While updating the file to the current SDK'
 | |
|                             f' version, the node {node.name} in tree'
 | |
|                             f' {tree.name} is no variable node but had'
 | |
|                             ' a logic ID. The logic ID was reset to'
 | |
|                             ' prevent undefined behaviour.'
 | |
|                         )
 | |
|                         node.lnx_logic_id = ''
 | |
|                         continue
 | |
| 
 | |
|                     if node.lnx_logic_id in tv_nodes:
 | |
|                         tv_nodes[node.lnx_logic_id].append(node)
 | |
| 
 | |
|                         # Check for getter nodes and type conflicts
 | |
|                         cur_type = tv_types[node.lnx_logic_id]
 | |
|                         if cur_type == 'LNDynamicNode':
 | |
|                             tv_types[node.lnx_logic_id] = node.bl_idname
 | |
|                         elif cur_type != node.bl_idname and node.bl_idname != 'LNDynamicNode':
 | |
|                             lnx.log.warn(
 | |
|                                 'Found nodes of different types with the'
 | |
|                                 ' same logic ID while updating the file'
 | |
|                                 ' to the current SDK version (undefined'
 | |
|                                 ' behaviour).\n'
 | |
|                                 f'\tConflicting types: {cur_type}, {node.bl_idname}\n'
 | |
|                                 f'\tLogic ID: {node.lnx_logic_id}\n'
 | |
|                                 f'\tNew type for both nodes: {cur_type}'
 | |
|                             )
 | |
|                     else:
 | |
|                         tv_nodes[node.lnx_logic_id] = [node]
 | |
|                         tv_types[node.lnx_logic_id] = node.bl_idname
 | |
| 
 | |
|             # Second pass: add the tree variable and convert all found
 | |
|             # tree var nodes to the correct type
 | |
|             for logic_id in tv_nodes.keys():
 | |
|                 var_type = tv_types[logic_id]
 | |
| 
 | |
|                 var_item = LNX_PG_TreeVarListItem.create_new(tree, logic_id, var_type)
 | |
| 
 | |
|                 for node in tv_nodes[logic_id]:
 | |
|                     if node.bl_idname != var_type:
 | |
|                         newnode = tree.nodes.new(var_type)
 | |
|                         lnx.node_utils.copy_basic_node_props(from_node=node, to_node=newnode)
 | |
| 
 | |
|                         # Connect outputs as good as possible
 | |
|                         for i in range(min(len(node.outputs), len(newnode.outputs))):
 | |
|                             for out in node.outputs:
 | |
|                                 for link in out.links:
 | |
|                                     tree.links.new(newnode.outputs[i], link.to_socket)
 | |
| 
 | |
|                         tree.nodes.remove(node)
 | |
|                         node = newnode
 | |
| 
 | |
|                     # Hide sockets
 | |
|                     node.on_logic_id_change()
 | |
| 
 | |
|                     node.use_custom_color = True
 | |
|                     node.color = var_item.color
 | |
| 
 | |
|                 lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin.choose_new_master_node(tree, logic_id)
 | |
| 
 | |
| 
 | |
| def node_compat_sdk2209():
 | |
|     # See https://github.com/leenkx3d/leenkx/pull/2538
 | |
|     for tree in bpy.data.node_groups:
 | |
|         if tree.bl_idname == "LnxLogicTreeType":
 | |
|             for item in tree.lnx_treevariableslist:
 | |
|                 lnx.logicnode.lnx_nodes.LnxLogicVariableNodeMixin.synchronize(tree, item.name)
 | |
| 
 | |
| 
 | |
| __REG_CLASSES = (
 | |
|     LNX_PT_Variables,
 | |
|     LNX_OT_TreeVariableListMoveItem,
 | |
|     LNX_OT_TreeVariableMakeLocalNode,
 | |
|     LNX_OT_TreeVariableVariableAssignToNode,
 | |
|     LNX_OT_TreeVariablePromoteNode,
 | |
|     LNX_OT_AddVarGetterNode,
 | |
|     LNX_OT_AddVarSetterNode,
 | |
|     LNX_UL_TreeVarList,
 | |
|     LNX_PG_TreeVarListItem,
 | |
| )
 | |
| __reg_classes, __unreg_classes = bpy.utils.register_classes_factory(__REG_CLASSES)
 | |
| 
 | |
| 
 | |
| def register():
 | |
|     __reg_classes()
 | |
| 
 | |
|     bpy.types.Node.lnx_logic_id = StringProperty(
 | |
|         name='ID',
 | |
|         description='Nodes with equal identifier share data',
 | |
|         default='',
 | |
|         update=on_update_node_logic_id
 | |
|     )
 | |
| 
 | |
|     bpy.types.NodeTree.lnx_treevariableslist = CollectionProperty(type=LNX_PG_TreeVarListItem)
 | |
|     bpy.types.NodeTree.lnx_treevariableslist_index = IntProperty(name='Index for lnx_variableslist', default=0)
 | |
| 
 | |
| 
 | |
| def unregister():
 | |
|     __unreg_classes()
 |