#!/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')