try: from bpy.types import NodeSocketInterfaceInt except: from bpy.types import NodeTreeInterfaceSocketInt from lnx.logicnode.lnx_nodes import * class SelectNode(LnxLogicTreeNode): """Selects one of multiple values (of arbitrary types) based on some input state. The exact behaviour of this node is specified by the `Execution Mode` option (see below). @output Out: [*Available if Execution Mode is set to From Input*] Activated after the node was executed. @output Value: The last selected value. This value is not reset until the next execution of this node. @option Execution Mode: Specifies the condition that determines what value to choose. - `From Index`: Select the value at the given index. If there is no value at that index, the value plugged in to the `Default` input is used instead (`null` if unconnected). - `From Input`: This mode uses input pairs of one action socket and one value socket. Depending on which action socket is activated, the associated value socket (the value with the same index as the activated action input) is forwarded to the `Value` output. @option New: Add a new value to the list of values. @option X Button: Remove the value with the highest index.""" bl_idname = 'LNSelectNode' bl_label = 'Select' lnx_version = 2 min_inputs = 2 def update_exec_mode(self, context): self.set_mode() property0: HaxeEnumProperty( 'property0', name='Execution Mode', description="The node's behaviour.", items=[ ('from_index', 'From Index', 'Choose the value from the given index'), ('from_input', 'From Input', 'Choose the value with the same position as the active input')], default='from_index', update=update_exec_mode, ) # The number of choices, NOT of individual inputs. This needs to be # a property in order to be saved with each individual node num_choices: IntProperty(default=1, min=0) def __init__(self): super().__init__() array_nodes[str(id(self))] = self def lnx_init(self, context): self.set_mode() def set_mode(self): self.inputs.clear() self.outputs.clear() if self.property0 == 'from_index': self.add_input('LnxIntSocket', 'Index') self.add_input('LnxDynamicSocket', 'Default') self.num_choices = 0 # from_input else: # We could also start with index 1 here, but we need to use # 0 for the "from_index" mode and it makes the code simpler # if we stick to the same convention for both exec modes self.add_input('LnxNodeSocketAction', 'Input 0') self.add_input('LnxDynamicSocket', 'Value 0') self.num_choices = 1 self.add_output('LnxNodeSocketAction', 'Out') self.add_output('LnxDynamicSocket', 'Value') def draw_buttons(self, context, layout): layout.prop(self, 'property0', text='') row = layout.row(align=True) op = row.operator('lnx.node_call_func', text='New', icon='PLUS', emboss=True) op.node_index = str(id(self)) op.callback_name = 'add_input_func' column = row.column(align=True) op = column.operator('lnx.node_call_func', text='', icon='X', emboss=True) op.node_index = str(id(self)) op.callback_name = 'remove_input_func' if len(self.inputs) == self.min_inputs: column.enabled = False def add_input_func(self): if self.property0 == 'from_input': self.add_input('LnxNodeSocketAction', f'Input {self.num_choices}') # Move new action input up to the end of all other action inputs self.inputs.move(from_index=len(self.inputs) - 1, to_index=self.num_choices) self.add_input('LnxDynamicSocket', f'Value {self.num_choices}') self.num_choices += 1 def remove_input_func(self): if self.property0 == 'from_input': if len(self.inputs) > self.min_inputs: self.inputs.remove(self.inputs[self.num_choices - 1]) if len(self.inputs) > self.min_inputs: self.inputs.remove(self.inputs[-1]) self.num_choices -= 1 def draw_label(self) -> str: if self.num_choices == 0: return self.bl_label return f'{self.bl_label}: [{self.num_choices}]' def get_replacement_node(self, node_tree: bpy.types.NodeTree): if self.lnx_version not in (0, 1): raise LookupError() return NodeReplacement.Identity(self)