Fixed Timing / Data Update Logic / Low Health Overlay Issues / Comparison Node and Math Node issues.

This commit is contained in:
2025-02-15 23:18:58 -07:00
parent d9623193d8
commit 6bac303dea
16 changed files with 292 additions and 557 deletions

View File

@ -1,15 +1,15 @@
#!/usr/bin/env python3
"""
Comparison Node:
- Inputs: Two input ports ("A" and "B").
- Output: One output port ("Result").
- Operation: A dropdown (combo menu) to select:
Equal (==), Not Equal (!=), Greater Than (>), Less Than (<),
Greater Than or Equal (>=), Less Than or Equal (<=).
- Displays the computed result in a read-only text box labeled "Result".
Standardized Comparison Node:
- Compares two input values using a selected operator (==, !=, >, <, >=, <=).
- Outputs a result of 1 (True) or 0 (False).
- Uses a global update timer for processing.
- Supports an additional 'Input Type' dropdown to choose between 'Number' and 'String'.
"""
from OdenGraphQt import BaseNode
from Qt import QtCore
class ComparisonNode(BaseNode):
__identifier__ = 'bunny-lab.io.comparison_node'
@ -17,112 +17,106 @@ class ComparisonNode(BaseNode):
def __init__(self):
super(ComparisonNode, self).__init__()
# ----------------------------------------------------------------------
# Initialization Section:
# - Create two input ports: A, B
# - Create one output port: Result
# - Add a combo box for logical operator selection
# - Add a text input for displaying the computed result
# ----------------------------------------------------------------------
self.add_input('A')
self.add_input('B')
self.add_output('Result')
# Operator combo box (==, !=, >, <, >=, <=)
# Add the Input Type dropdown first.
self.add_combo_menu('input_type', 'Input Type', items=['Number', 'String'])
self.add_combo_menu('operator', 'Operator', items=[
'Equal (==)',
'Not Equal (!=)',
'Greater Than (>)',
'Less Than (<)',
'Greater Than or Equal (>=)',
'Less Than or Equal (<=)'
'Equal (==)', 'Not Equal (!=)', 'Greater Than (>)',
'Less Than (<)', 'Greater Than or Equal (>=)', 'Less Than or Equal (<=)'
])
# Text input for displaying the computed result.
# We'll make it read-only by accessing the underlying QLineEdit.
self.add_text_input('calc_result', 'Result', text='0')
result_widget = self.get_widget('calc_result') # This is a NodeLineEdit wrapper
if result_widget:
# Get the underlying QLineEdit
line_edit = result_widget.get_custom_widget()
# Make the QLineEdit read-only
line_edit.setReadOnly(True)
# Replace calc_result with a standardized "value" text input.
self.add_text_input('value', 'Value', text='0')
self.value = 0
self.set_name("Comparison Node")
self.process_input()
self.processing = False # Guard for process_input
def process_input(self, event=None):
"""
Compute Section:
- For each input port (A, B), if connected, grab the 'value' from
the upstream node; otherwise default to 0.0.
- Convert to float when possible, apply the selected comparison operator,
update the "Result" text box, node title, and output port.
"""
# Gather input A
# Set default properties explicitly
self.set_property('input_type', 'Number')
self.set_property('operator', 'Equal (==)')
def process_input(self):
if self.processing:
return
self.processing = True
# Retrieve input values; if no connection or None, default to "0"
input_a = self.input(0)
if input_a and input_a.connected_ports():
a_raw = input_a.connected_ports()[0].node().get_property('value')
else:
a_raw = 0.0
# Gather input B
input_b = self.input(1)
if input_b and input_b.connected_ports():
b_raw = input_b.connected_ports()[0].node().get_property('value')
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")
a_raw = a_raw if a_raw is not None else "0"
b_raw = b_raw if b_raw is not None else "0"
# Get input type property
input_type = self.get_property('input_type')
# Convert values based on input type
if input_type == 'Number':
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
elif input_type == 'String':
a_val = str(a_raw)
b_val = str(b_raw)
else:
b_raw = 0.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
# Convert raw inputs to float if possible, otherwise keep as-is for string comparison.
try:
a_val = float(a_raw)
b_val = float(b_raw)
except (ValueError, TypeError):
a_val = a_raw
b_val = b_raw
# Retrieve the selected operator from the combo box.
operator = self.get_property('operator')
result = False
if operator == 'Equal (==)':
result = a_val == b_val
elif operator == 'Not Equal (!=)':
result = a_val != b_val
elif operator == 'Greater Than (>)':
result = a_val > b_val
elif operator == 'Less Than (<)':
result = a_val < b_val
elif operator == 'Greater Than or Equal (>=)':
result = a_val >= b_val
elif operator == 'Less Than or Equal (<=)':
result = a_val <= b_val
# Convert boolean result to integer (1 for True, 0 for False)
self.value = 1 if result else 0
# Update the read-only text input and node title.
self.set_property('calc_result', str(self.value))
# Transmit the numeric result to any connected output nodes.
output_port = self.output(0)
if output_port and output_port.connected_ports():
for cp in output_port.connected_ports():
connected_node = cp.node()
if hasattr(connected_node, 'receive_data'):
connected_node.receive_data(self.value, source_port_name='Result')
# Perform the comparison
result = {
'Equal (==)': a_val == b_val,
'Not Equal (!=)': a_val != b_val,
'Greater Than (>)': a_val > b_val,
'Less Than (<)': a_val < b_val,
'Greater Than or Equal (>=)': a_val >= b_val,
'Less Than or Equal (<=)': a_val <= b_val
}.get(operator, False)
new_value = 1 if result else 0
self.value = new_value
self.set_property('value', str(self.value))
self.transmit_data(self.value)
self.processing = False
def on_input_connected(self, input_port, output_port):
self.process_input()
pass
def on_input_disconnected(self, input_port, output_port):
self.process_input()
pass
def property_changed(self, property_name):
if property_name in ['operator']:
self.process_input()
pass
def receive_data(self, data, source_port_name=None):
self.process_input()
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:
data_int = int(data)
connected_node.receive_data(data_int, source_port_name='Result')
except ValueError:
pass