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
|
distance = (mouse_vector - last_point).length
|
||||||
if distance < 0:
|
if distance < 0:
|
||||||
return
|
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:
|
if distance > 0:
|
||||||
angle = tool.Cad.angle_3_vectors(
|
angle = tool.Cad.angle_3_vectors(
|
||||||
second_to_last_point, last_point, mouse_vector, new_angle=None, degrees=True
|
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
|
# Round angle to the nearest 0.05
|
||||||
angle = round(angle / 0.05) * 0.05 if distance < angle_round_threshold else angle
|
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
|
angle = 0
|
||||||
orientation_angle = 0
|
orientation_angle = 0
|
||||||
if input_ui:
|
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:
|
if should_round:
|
||||||
angle_snap = tool.Snap.get_angle_snap_value(context)
|
angle_snap = tool.Snap.get_angle_snap_value(context)
|
||||||
angle = angle_snap * round(angle / angle_snap) if distance < angle_round_threshold else angle
|
angle = angle_snap * round(angle / angle_snap) if distance < angle_round_threshold else angle
|
||||||
|
|||||||
@@ -56,3 +56,31 @@ class TestValidateInput(NewFile):
|
|||||||
|
|
||||||
# Angle.
|
# Angle.
|
||||||
assert subject.validate_input("25", "A") == (True, "25.0")
|
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