| 
									
										
										
										
											2025-01-22 16:18:30 +01:00
										 |  |  | from lnx.logicnode.lnx_nodes import * | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MathNode(LnxLogicTreeNode): | 
					
						
							|  |  |  |     """Mathematical operations on values.""" | 
					
						
							|  |  |  |     bl_idname = 'LNMathNode' | 
					
						
							|  |  |  |     bl_label = 'Math' | 
					
						
							|  |  |  |     lnx_version = 3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def get_enum_id_value(obj, prop_name, value): | 
					
						
							|  |  |  |         return obj.bl_rna.properties[prop_name].enum_items[value].identifier | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def get_count_in(operation_name): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             'Add': 0, | 
					
						
							|  |  |  |             'Subtract': 0, | 
					
						
							|  |  |  |             'Multiply': 0, | 
					
						
							|  |  |  |             'Divide': 0, | 
					
						
							|  |  |  |             'Sine': 1, | 
					
						
							|  |  |  |             'Cosine': 1, | 
					
						
							|  |  |  |             'Abs': 1, | 
					
						
							|  |  |  |             'Tangent': 1, | 
					
						
							|  |  |  |             'Arcsine': 1, | 
					
						
							|  |  |  |             'Arccosine': 1, | 
					
						
							|  |  |  |             'Arctangent': 1, | 
					
						
							|  |  |  |             'Logarithm': 1, | 
					
						
							|  |  |  |             'Round': 2, | 
					
						
							|  |  |  |             'Floor': 1, | 
					
						
							|  |  |  |             'Ceil': 1, | 
					
						
							|  |  |  |             'Square Root': 1, | 
					
						
							|  |  |  |             'Fract': 1, | 
					
						
							|  |  |  |             'Exponent': 1, | 
					
						
							|  |  |  |             'Max': 2, | 
					
						
							|  |  |  |             'Min': 2, | 
					
						
							|  |  |  |             'Power': 2, | 
					
						
							|  |  |  |             'Arctan2': 2, | 
					
						
							|  |  |  |             'Modulo': 2, | 
					
						
							|  |  |  |             'Less Than': 2, | 
					
						
							|  |  |  |             'Greater Than': 2, | 
					
						
							|  |  |  |             'Ping-Pong': 2 | 
					
						
							|  |  |  |         }.get(operation_name, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_enum(self): | 
					
						
							|  |  |  |         return self.get('property0', 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_enum(self, value): | 
					
						
							|  |  |  |         # Checking the selection of another operation | 
					
						
							|  |  |  |         select_current = self.get_enum_id_value(self, 'property0', value) | 
					
						
							|  |  |  |         select_prev = self.property0 | 
					
						
							|  |  |  |         if select_prev != select_current: | 
					
						
							|  |  |  |             # Many arguments: Add, Subtract, Multiply, Divide | 
					
						
							|  |  |  |             if (self.get_count_in(select_current) == 0): | 
					
						
							|  |  |  |                 while (len(self.inputs) < 2): | 
					
						
							|  |  |  |                     self.add_input('LnxFloatSocket', 'Value ' + str(len(self.inputs))) | 
					
						
							|  |  |  |             # 2 arguments: Max, Min, Power, Arctan2, Modulo, Less Than, Greater Than, Ping-Pong | 
					
						
							|  |  |  |             if (self.get_count_in(select_current) == 2): | 
					
						
							|  |  |  |                 while (len(self.inputs) > 2): | 
					
						
							|  |  |  |                     self.inputs.remove(self.inputs.values()[-1]) | 
					
						
							|  |  |  |                 while (len(self.inputs) < 2): | 
					
						
							|  |  |  |                     self.add_input('LnxFloatSocket', 'Value ' + str(len(self.inputs))) | 
					
						
							|  |  |  |             # 1 argument: Sine, Cosine, Abs, Tangent, Arcsine, Arccosine, Arctangent, Logarithm, Round, Floor, Ceil, Square Root, Fract, Exponent | 
					
						
							|  |  |  |             if (self.get_count_in(select_current) == 1): | 
					
						
							|  |  |  |                 while (len(self.inputs) > 1): | 
					
						
							|  |  |  |                     self.inputs.remove(self.inputs.values()[-1]) | 
					
						
							|  |  |  |         self['property0'] = value | 
					
						
							|  |  |  |         if (self.property0 == 'Round'): | 
					
						
							|  |  |  |             self.inputs[1].name = 'Precision' | 
					
						
							|  |  |  |         elif (self.property0 == 'Ping-Pong'): | 
					
						
							|  |  |  |             self.inputs[1].name = 'Scale' | 
					
						
							|  |  |  |         elif (len(self.inputs) > 1): self.inputs[1].name = 'Value 1' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     property0: HaxeEnumProperty( | 
					
						
							|  |  |  |         'property0', | 
					
						
							|  |  |  |         items = [('Add', 'Add', 'Add'), | 
					
						
							|  |  |  |                  ('Multiply', 'Multiply', 'Multiply'), | 
					
						
							|  |  |  |                  ('Sine', 'Sine', 'Sine'), | 
					
						
							|  |  |  |                  ('Cosine', 'Cosine', 'Cosine'), | 
					
						
							|  |  |  |                  ('Max', 'Maximum', 'Max'), | 
					
						
							|  |  |  |                  ('Min', 'Minimum', 'Min'), | 
					
						
							|  |  |  |                  ('Abs', 'Absolute', 'Abs'), | 
					
						
							|  |  |  |                  ('Subtract', 'Subtract', 'Subtract'), | 
					
						
							|  |  |  |                  ('Divide', 'Divide', 'Divide'), | 
					
						
							|  |  |  |                  ('Tangent', 'Tangent', 'Tangent'), | 
					
						
							|  |  |  |                  ('Arcsine', 'Arcsine', 'Arcsine'), | 
					
						
							|  |  |  |                  ('Arccosine', 'Arccosine', 'Arccosine'), | 
					
						
							|  |  |  |                  ('Arctangent', 'Arctangent', 'Arctangent'), | 
					
						
							|  |  |  |                  ('Power', 'Power', 'Power'), | 
					
						
							|  |  |  |                  ('Logarithm', 'Logarithm', 'Logarithm'), | 
					
						
							|  |  |  |                  ('Round', 'Round', 'Round (Value 1 precision of decimal places)'), | 
					
						
							|  |  |  |                  ('Less Than', 'Less Than', 'Less Than'), | 
					
						
							|  |  |  |                  ('Greater Than', 'Greater Than', 'Greater Than'), | 
					
						
							|  |  |  |                  ('Modulo', 'Modulo', 'Modulo'), | 
					
						
							|  |  |  |                  ('Arctan2', 'Arctan2', 'Arctan2'), | 
					
						
							|  |  |  |                  ('Floor', 'Floor', 'Floor'), | 
					
						
							|  |  |  |                  ('Ceil', 'Ceil', 'Ceil'), | 
					
						
							|  |  |  |                  ('Fract', 'Fract', 'Fract'), | 
					
						
							|  |  |  |                  ('Square Root', 'Square Root', 'Square Root'), | 
					
						
							|  |  |  |                  ('Exponent', 'Exponent', 'Exponent'), | 
					
						
							|  |  |  |                  ('Ping-Pong', 'Ping-Pong', 'The output value is moved between 0.0 and the Scale based on the input value')], | 
					
						
							|  |  |  |         name='', default='Add', set=set_enum, get=get_enum) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     property1: HaxeBoolProperty('property1', name='Clamp', default=False) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-06 10:16:57 +00:00
										 |  |  |     def __init__(self, *args, **kwargs): | 
					
						
							|  |  |  |         super(MathNode, self).__init__(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2025-01-22 16:18:30 +01:00
										 |  |  |         array_nodes[str(id(self))] = self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def lnx_init(self, context): | 
					
						
							|  |  |  |         self.add_input('LnxFloatSocket', 'Value 0', default_value=0.0) | 
					
						
							|  |  |  |         self.add_input('LnxFloatSocket', 'Value 1', default_value=0.0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.add_output('LnxFloatSocket', 'Result') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def draw_buttons(self, context, layout): | 
					
						
							|  |  |  |         layout.prop(self, 'property1') | 
					
						
							|  |  |  |         layout.prop(self, 'property0') | 
					
						
							|  |  |  |         # Many arguments: Add, Subtract, Multiply, Divide | 
					
						
							|  |  |  |         if (self.get_count_in(self.property0) == 0): | 
					
						
							|  |  |  |             row = layout.row(align=True) | 
					
						
							|  |  |  |             column = row.column(align=True) | 
					
						
							|  |  |  |             op = column.operator('lnx.node_add_input', text='Add Value', icon='PLUS', emboss=True) | 
					
						
							|  |  |  |             op.node_index = str(id(self)) | 
					
						
							|  |  |  |             op.socket_type = 'LnxFloatSocket' | 
					
						
							|  |  |  |             op.name_format = 'Value {0}' | 
					
						
							|  |  |  |             column = row.column(align=True) | 
					
						
							|  |  |  |             op = column.operator('lnx.node_remove_input', text='', icon='X', emboss=True) | 
					
						
							|  |  |  |             op.node_index = str(id(self)) | 
					
						
							|  |  |  |             if len(self.inputs) == 2: | 
					
						
							|  |  |  |                 column.enabled = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def draw_label(self) -> str: | 
					
						
							|  |  |  |         return f'{self.bl_label}: {self.property0}' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_replacement_node(self, node_tree: bpy.types.NodeTree): | 
					
						
							|  |  |  |         if self.lnx_version not in (0, 2): | 
					
						
							|  |  |  |             raise LookupError() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return NodeReplacement.Identity(self) |