mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-05 23:41:44 +00:00
Bonsai: fix UnboundLocalError crash in polyline angle calculation
angle_round_threshold was only assigned inside the `distance > 0` branch of calculate_distance_and_angle, but read unconditionally whenever should_round is True. When the mouse sample coincides with the last placed point (distance == 0), such as the first mouse move after placing a wall's start point on a YZ plane view, this crashed the modal wall tool. angle_round_threshold is a fixed cutoff unrelated to whether distance is currently zero, so it is now assigned once before the branch. Fixes #8597. Generated with the assistance of an AI coding tool.
This commit is contained in:
committed by
Dion Moult
parent
51ab38de27
commit
89523999b3
@@ -168,12 +168,12 @@ class Polyline(bonsai.core.tool.Polyline):
|
||||
distance = (mouse_vector - last_point).length
|
||||
if distance < 0:
|
||||
return
|
||||
angle, orientation_angle, angle_round_threshold = None, None, None
|
||||
angle, orientation_angle = None, None
|
||||
angle_round_threshold = 1000 # Avoids rounding when distance is too big
|
||||
if distance > 0:
|
||||
angle = tool.Cad.angle_3_vectors(
|
||||
second_to_last_point, last_point, mouse_vector, new_angle=None, degrees=True
|
||||
)
|
||||
angle_round_threshold = 1000 # Avoids rounding when distance is too big
|
||||
|
||||
# Round angle to the nearest 0.05
|
||||
angle = round(angle / 0.05) * 0.05 if distance < angle_round_threshold else angle
|
||||
@@ -189,7 +189,7 @@ class Polyline(bonsai.core.tool.Polyline):
|
||||
angle = 0
|
||||
orientation_angle = 0
|
||||
if input_ui:
|
||||
assert angle is not None and orientation_angle is not None and angle_round_threshold is not None
|
||||
assert angle is not None and orientation_angle is not None
|
||||
if should_round:
|
||||
angle_snap = tool.Snap.get_angle_snap_value(context)
|
||||
angle = angle_snap * round(angle / angle_snap) if distance < angle_round_threshold else angle
|
||||
|
||||
@@ -56,3 +56,31 @@ class TestValidateInput(NewFile):
|
||||
|
||||
# Angle.
|
||||
assert subject.validate_input("25", "A") == (True, "25.0")
|
||||
|
||||
|
||||
class TestCalculateDistanceAndAngle(NewFile):
|
||||
def test_it_does_not_crash_when_distance_is_zero_and_should_round(self, monkeypatch):
|
||||
# Regression test for #8597: right after placing the first polyline
|
||||
# point, the initial mouse sample can equal the last placed point
|
||||
# (distance == 0), e.g. entering the viewport on a YZ plane wall.
|
||||
# angle_round_threshold used to only be assigned in the
|
||||
# `distance > 0` branch, crashing when should_round reads it here.
|
||||
# get_increment_snap_value requires a real 3D viewport rv3d, which
|
||||
# is unrelated to this bug, so it's stubbed out for a headless run.
|
||||
monkeypatch.setattr(tool.Snap, "get_increment_snap_value", classmethod(lambda cls, context: 1.0))
|
||||
|
||||
polyline_props = tool.Model.get_polyline_props()
|
||||
mouse_point = polyline_props.snap_mouse_point.add()
|
||||
mouse_point.x, mouse_point.y, mouse_point.z = 0, 0, 0
|
||||
|
||||
tool_state = subject.create_tool_state()
|
||||
tool_state.is_input_on = False
|
||||
tool_state.use_default_container = False
|
||||
tool_state.plane_method = "YZ"
|
||||
|
||||
input_ui = subject.create_input_ui(input_options=["D", "A", "X", "Y", "Z"])
|
||||
|
||||
subject.calculate_distance_and_angle(bpy.context, input_ui, tool_state, should_round=True)
|
||||
|
||||
assert input_ui.get_number_value("D") == 0
|
||||
assert input_ui.get_number_value("A") == 0
|
||||
|
||||
Reference in New Issue
Block a user