Hello fellow designers and coders,
I am new to python especially the 3.0 implemented within grasshopper within Rhino 8.0
Very curious about the possibility to have a python component read a slider either current, min and max values and then generate steps based on a Component ie float names Frames that can push the slider from its min to max value by a function such as steps = (Max-min)/Frames
I think it’s clear I am working on a animation component and am having come issues with this last part.
This is what I have thus far:
from decimal import Decimal, getcontext
import Grasshopper as gh
from Grasshopper.Kernel.Special import GH_Group, GH_NumberSlider
import System
# Set decimal precision
getcontext().prec = 28
def safe_decimal(val):
"""Convert ANY numeric type to Python Decimal"""
if val is None:
return Decimal('0')
try:
if hasattr(val, 'ToString'): # .NET object
return Decimal(str(val))
return Decimal(str(val))
except:
return Decimal('0')
def safe_int(val):
"""Convert ANY numeric type to int"""
if val is None:
return 0
try:
if hasattr(val, 'ToString'):
return int(float(str(val)))
return int(float(val))
except:
return 0
def to_net_decimal(val):
"""Convert Python Decimal to System.Decimal for Grasshopper outputs"""
if val is None:
return System.Decimal(0)
try:
return System.Decimal(float(val))
except:
return System.Decimal(0)
# Convert inputs
Frames = safe_decimal(Frames) if ‘Frames’ in locals() else Decimal(‘50’)
i = safe_int(i) if ‘i’ in locals() else 0
group_name = str(group_name) if ‘group_name’ in locals() else “Animate”
doc = ghenv.Component.OnPingDocument()
found_slider = None
min_val = max_val = step = None
current_val = None
slider_name = None
frame_idx = 0
if doc:
for obj in doc.Objects:
if isinstance(obj, GH_Group) and str(obj.NickName) == group_name:
for comp in obj.Objects():
if isinstance(comp, GH_NumberSlider):
found_slider = comp
break
if found_slider:
break
if found_slider and Frames > 0:
\# Read slider bounds
min_val = safe_decimal(found_slider.Slider.Minimum)
max_val = safe_decimal(found_slider.Slider.Maximum)
\# Compute step
if Frames > Decimal('1'):
step = (max_val - min_val) / (Frames - Decimal('1'))
else:
step = Decimal('0')
\# Clamp frame index
max_frame = min(safe_int(Frames), 999999)
frame_idx = max(0, min(safe_int(i), max_frame - 1))
\# Compute target value
target_val = min_val + (step \* Decimal(frame_idx))
\# Set slider value (must be float for .NET)
found_slider.Slider.Value = float(target_val)
found_slider.ExpireSolution(True)
current_val = target_val
slider_name = str(found_slider.NickName)
# CRITICAL FIX: Convert ALL outputs to System.Decimal
a_min = to_net_decimal(min_val)
a_max = to_net_decimal(max_val)
a_step = to_net_decimal(step)
a_val = to_net_decimal(current_val)
a_idx = frame_idx # This is already int, safe
slider_name = slider_name if slider_name else “”
Current issue:
Traceback (most recent call last):
File “rhinocode:///grasshopper/1/58edebc1-834a-4506-b38e-b45c3c5b0e5e/bbac34bc-7726-4a2f-85f8-aabeac8647f1”, line 81, in
TypeError: ‘float’ value cannot be converted to System.Decimal
I would be glad to share the final animation code as I believe it would benefit the entire community!
Best regards and thanks for your contribution,
Andres