153 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from lnx.logicnode.lnx_nodes import *
 | |
| 
 | |
| 
 | |
| class VectorMathNode(LnxLogicTreeNode):
 | |
|     """Mathematical operations on vectors."""
 | |
|     bl_idname = 'LNVectorMathNode'
 | |
|     bl_label = 'Vector Math'
 | |
|     lnx_section = 'vector'
 | |
|     lnx_version = 1
 | |
| 
 | |
|     def get_bool(self):
 | |
|         return self.get('property1', False)
 | |
| 
 | |
|     def set_bool(self, value):
 | |
|         self['property1'] = value
 | |
|         if value:
 | |
|             if self.property0 in ('Length', 'Distance', 'Dot Product'):
 | |
|                 self.outputs.remove(self.outputs.values()[-1])  # Distance/Length/Scalar
 | |
|             self.add_output('LnxFloatSocket', 'X')  # Result X
 | |
|             self.add_output('LnxFloatSocket', 'Y')  # Result Y
 | |
|             self.add_output('LnxFloatSocket', 'Z')  # Result Z
 | |
|             if self.property0 == 'Length':
 | |
|                 self.add_output('LnxFloatSocket', 'Length')  # Length
 | |
|             if self.property0 == 'Distance':
 | |
|                 self.add_output('LnxFloatSocket', 'Distance')  # Distance
 | |
|             if self.property0 == 'Dot Product':
 | |
|                 self.add_output('LnxFloatSocket', 'Scalar')  # Scalar
 | |
|         else:
 | |
|             if self.property0 in ('Length', 'Distance', 'Dot Product') and len(self.outputs) > 1:
 | |
|                 self.outputs.remove(self.outputs.values()[-1])  # Distance/Length/Scalar
 | |
|             # Remove X, Y, Z
 | |
|             for i in range(3):
 | |
|                 if len(self.outputs) > 1:
 | |
|                     self.outputs.remove(self.outputs.values()[-1])
 | |
|                 else:
 | |
|                     break
 | |
|             if self.property0 == 'Length':
 | |
|                 self.add_output('LnxFloatSocket', 'Length')  # Length
 | |
|             if self.property0 == 'Distance':
 | |
|                 self.add_output('LnxFloatSocket', 'Distance')  # Distance
 | |
|             if self.property0 == 'Dot Product':
 | |
|                 self.add_output('LnxFloatSocket', 'Scalar')  # Scalar
 | |
| 
 | |
|     property1: HaxeBoolProperty('property1', name='Separator Out', default=False, set=set_bool, get=get_bool)
 | |
| 
 | |
|     @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,
 | |
|             'Average': 0,
 | |
|             'Dot Product': 0,
 | |
|             'Cross Product': 0,
 | |
|             'Multiply': 0,
 | |
|             'MultiplyFloats': 0,
 | |
|             'Distance': 2,
 | |
|             'Reflect': 2,
 | |
|             'Normalize': 1,
 | |
|             'Length': 1
 | |
|         }.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:
 | |
|             if select_prev in ('Distance', 'Length', 'Dot Product'):
 | |
|                 self.outputs.remove(self.outputs.values()[-1])
 | |
|             # Many arguments: Add, Subtract, Average, Dot Product, Cross Product, Multiply, MultiplyFloats
 | |
|             if self.get_count_in(select_current) == 0:
 | |
|                 if select_current == "MultiplyFloats" or select_prev == "MultiplyFloats":
 | |
|                     while (len(self.inputs) > 1):
 | |
|                         self.inputs.remove(self.inputs.values()[-1])
 | |
|                 if select_current == "MultiplyFloats":
 | |
|                     self.add_input('LnxFloatSocket', 'Value ' + str(len(self.inputs)))
 | |
|                 else:
 | |
|                     while (len(self.inputs) < 2):
 | |
|                         self.add_input('LnxVectorSocket', 'Value ' + str(len(self.inputs)))
 | |
|                 if select_current == 'Dot Product':
 | |
|                     self.add_output('LnxFloatSocket', 'Scalar')
 | |
|                 # 2 arguments: Distance, Reflect
 | |
|             if self.get_count_in(select_current) == 2:
 | |
|                 count = 2
 | |
|                 if select_prev == "MultiplyFloats":
 | |
|                     count = 1
 | |
|                 while len(self.inputs) > count:
 | |
|                     self.inputs.remove(self.inputs.values()[-1])
 | |
|                 while len(self.inputs) < 2:
 | |
|                     self.add_input('LnxVectorSocket', 'Value ' + str(len(self.inputs)))
 | |
|                 if select_current == 'Distance':
 | |
|                     self.add_output('LnxFloatSocket', 'Distance')
 | |
|             # 1 argument: Normalize, Length
 | |
|             if self.get_count_in(select_current) == 1:
 | |
|                 while len(self.inputs) > 1:
 | |
|                     self.inputs.remove(self.inputs.values()[-1])
 | |
|                 if select_current == 'Length':
 | |
|                     self.add_output('LnxFloatSocket', 'Length')
 | |
|         self['property0'] = value
 | |
| 
 | |
|     property0: HaxeEnumProperty(
 | |
|         'property0',
 | |
|         items=[('Add', 'Add', 'Add'),
 | |
|                ('Dot Product', 'Dot Product', 'Dot Product'),
 | |
|                ('Multiply', 'Multiply', 'Multiply'),
 | |
|                ('MultiplyFloats', 'Multiply (Floats)', 'Multiply (Floats)'),
 | |
|                ('Normalize', 'Normalize', 'Normalize'),
 | |
|                ('Subtract', 'Subtract', 'Subtract'),
 | |
|                ('Average', 'Average', 'Average'),
 | |
|                ('Cross Product', 'Cross Product', 'Cross Product'),
 | |
|                ('Length', 'Length', 'Length'),
 | |
|                ('Distance', 'Distance', 'Distance'),
 | |
|                ('Reflect', 'Reflect', 'Reflect')],
 | |
|         name='', default='Add', set=set_enum, get=get_enum)
 | |
| 
 | |
|     def __init__(self):
 | |
|         array_nodes[str(id(self))] = self
 | |
| 
 | |
|     def lnx_init(self, context):
 | |
|         self.add_input('LnxVectorSocket', 'Value 0', default_value=[0.0, 0.0, 0.0])
 | |
|         self.add_input('LnxVectorSocket', 'Value 1', default_value=[0.0, 0.0, 0.0])
 | |
| 
 | |
|         self.add_output('LnxVectorSocket', 'Result')
 | |
| 
 | |
|     def draw_buttons(self, context, layout):
 | |
|         layout.prop(self, 'property1')  # Separator Out
 | |
|         layout.prop(self, 'property0')  # Operation
 | |
|         # Buttons
 | |
|         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.name_format = 'Value {0}'
 | |
|             if self.property0 == "MultiplyFloats":
 | |
|                 op.socket_type = 'LnxFloatSocket'
 | |
|             else:
 | |
|                 op.socket_type = 'LnxVectorSocket'
 | |
|             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}'
 |