110 lines
3.9 KiB
Python
110 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Standardized Math Operation Node:
|
|
- Performs mathematical operations (+, -, *, /, avg) on two inputs.
|
|
- Outputs the computed result.
|
|
- Uses a global update timer for processing (defined in borealis.py).
|
|
- Ensures it always has a "value" property that the Comparison Node can read.
|
|
"""
|
|
|
|
from OdenGraphQt import BaseNode
|
|
from Qt import QtCore
|
|
|
|
class MathOperationNode(BaseNode):
|
|
__identifier__ = 'bunny-lab.io.math_node'
|
|
NODE_NAME = 'Math Operation'
|
|
|
|
def __init__(self):
|
|
super(MathOperationNode, self).__init__()
|
|
self.add_input('A')
|
|
self.add_input('B')
|
|
self.add_output('Result')
|
|
|
|
# Drop-down to choose which operation we do:
|
|
self.add_combo_menu('operator', 'Operator', items=[
|
|
'Add', 'Subtract', 'Multiply', 'Divide', 'Average'
|
|
])
|
|
|
|
# A text field for showing the result to the user:
|
|
self.add_text_input('calc_result', 'Result', text='0')
|
|
|
|
# IMPORTANT: define a "value" property that the Comparison Node can read
|
|
# We do not necessarily need a text input for it, but adding it ensures
|
|
# it becomes an official property recognized by OdenGraphQt.
|
|
self.add_text_input('value', 'Internal Value', text='0')
|
|
|
|
# Keep a Python-side float of the current computed result:
|
|
self.value = 0
|
|
|
|
# Give the node a nice name:
|
|
self.set_name("Math Operation")
|
|
|
|
# Removed self-contained timer; global timer calls process_input().
|
|
|
|
def process_input(self):
|
|
# Attempt to read "value" from both inputs:
|
|
input_a = self.input(0)
|
|
input_b = self.input(1)
|
|
a_raw = input_a.connected_ports()[0].node().get_property('value') if input_a.connected_ports() else "0"
|
|
b_raw = input_b.connected_ports()[0].node().get_property('value') if input_b.connected_ports() else "0"
|
|
|
|
try:
|
|
a_val = float(a_raw)
|
|
except (ValueError, TypeError):
|
|
a_val = 0.0
|
|
try:
|
|
b_val = float(b_raw)
|
|
except (ValueError, TypeError):
|
|
b_val = 0.0
|
|
|
|
operator = self.get_property('operator')
|
|
if operator == 'Add':
|
|
result = a_val + b_val
|
|
elif operator == 'Subtract':
|
|
result = a_val - b_val
|
|
elif operator == 'Multiply':
|
|
result = a_val * b_val
|
|
elif operator == 'Divide':
|
|
result = a_val / b_val if b_val != 0 else 0.0
|
|
elif operator == 'Average':
|
|
result = (a_val + b_val) / 2.0
|
|
else:
|
|
result = 0.0
|
|
|
|
# If the computed result changed, update our internal properties and transmit
|
|
if self.value != result:
|
|
self.value = result
|
|
|
|
# Update the two text fields so the user sees the numeric result:
|
|
self.set_property('calc_result', str(result))
|
|
self.set_property('value', str(result)) # <= This is the critical step
|
|
|
|
# Let downstream nodes know there's new data:
|
|
self.transmit_data(result)
|
|
|
|
def on_input_connected(self, input_port, output_port):
|
|
pass
|
|
|
|
def on_input_disconnected(self, input_port, output_port):
|
|
pass
|
|
|
|
def property_changed(self, property_name):
|
|
pass
|
|
|
|
def receive_data(self, data, source_port_name=None):
|
|
pass
|
|
|
|
def transmit_data(self, data):
|
|
output_port = self.output(0)
|
|
if output_port and output_port.connected_ports():
|
|
for connected_port in output_port.connected_ports():
|
|
connected_node = connected_port.node()
|
|
if hasattr(connected_node, 'receive_data'):
|
|
try:
|
|
# Attempt to convert to int if possible, else float
|
|
data_int = int(data)
|
|
connected_node.receive_data(data_int, source_port_name='Result')
|
|
except ValueError:
|
|
connected_node.receive_data(data, source_port_name='Result')
|