Fix issues with snapping empties and faceless objects in x-ray mode.

This commit is contained in:
Bruno Perdigão
2025-03-12 13:58:04 -03:00
parent b06ddbcad4
commit 5cc0aa71c7
+45 -31
View File
@@ -328,8 +328,19 @@ class Snap(bonsai.core.tool.Snap):
def cast_rays_to_single_object( def cast_rays_to_single_object(
obj: bpy.types.Object, mouse_pos: tuple[int, int] obj: bpy.types.Object, mouse_pos: tuple[int, int]
) -> Union[tuple[bpy.types.Object, Vector, int], tuple[None, None, None]]: ) -> Union[tuple[bpy.types.Object, Vector, int], tuple[None, None, None]]:
if obj.type != "MESH": hit = None
face_index = None
# Wireframes
if obj.type in {"EMPTY", "CURVE"} or (hasattr(obj.data, "polygons") and len(obj.data.polygons) == 0) :
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, obj)
if snap_points:
hit = sorted(snap_points, key=lambda x: x["distance"])[0]["point"]
if hit:
hit_world = obj.original.matrix_world @ hit
return obj, hit_world, face_index
return None, None, None return None, None, None
# Meshes
else:
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj) hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj)
if hit is None: if hit is None:
# Tried original mouse position. Now it will try the offsets. # Tried original mouse position. Now it will try the offsets.
@@ -407,24 +418,7 @@ class Snap(bonsai.core.tool.Snap):
point["group"] = "Measure" point["group"] = "Measure"
detected_snaps.append(point) detected_snaps.append(point)
# Edge-Vertex # Objects
for obj in objs_to_raycast:
if obj.type in {"MESH", "EMPTY"}:
# if len(obj.data.polygons) == 0:
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, obj)
if snap_points:
for point in snap_points:
point["group"] = "Edge-Vertex"
detected_snaps.append(point)
if obj.type == "CURVE":
new_object = bpy.data.objects.new("new_object", obj.to_mesh().copy())
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, new_object)
if snap_points:
for point in snap_points:
point["group"] = "Edge-Vertex"
detected_snaps.append(point)
# Obj
if (space.shading.type == "SOLID" and space.shading.show_xray) or ( if (space.shading.type == "SOLID" and space.shading.show_xray) or (
space.shading.type == "WIREFRAME" and space.shading.show_xray_wireframe space.shading.type == "WIREFRAME" and space.shading.show_xray_wireframe
): ):
@@ -434,11 +428,41 @@ class Snap(bonsai.core.tool.Snap):
else: else:
results = [] results = []
results.append(cast_rays_and_get_best_object(objs_to_raycast, mouse_pos)) results.append(cast_rays_and_get_best_object(objs_to_raycast, mouse_pos))
for result in results: for result in results:
snap_obj = result[0] snap_obj = result[0]
hit = result[1] hit = result[1]
face_index = result[2] face_index = result[2]
if hit is not None: if hit is not None:
# Wireframes
if snap_obj.type == "EMPTY" or (snap_obj.type == "MESH" and len(snap_obj.data.polygons) == 0):
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, snap_obj)
if snap_points:
for point in snap_points:
point["group"] = "Wireframe"
detected_snaps.append(point)
elif snap_obj.type == "CURVE":
new_object = bpy.data.objects.new("new_object", obj.to_mesh().copy())
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, new_object)
if snap_points:
for point in snap_points:
point["group"] = "Wireframe"
detected_snaps.append(point)
# Meshes
else:
# Add face snap
snap_point = {
"point": hit,
"type": "Face",
"group": "Object",
"object": snap_obj,
"face_index": face_index,
"distance": 9, # High value so it has low priority
}
detected_snaps.append(snap_point)
# Add vertex and edge snap
snap_points = tool.Raycast.ray_cast_by_proximity( snap_points = tool.Raycast.ray_cast_by_proximity(
context, event, snap_obj, snap_obj.data.polygons[face_index] context, event, snap_obj, snap_obj.data.polygons[face_index]
) )
@@ -446,16 +470,6 @@ class Snap(bonsai.core.tool.Snap):
for point in snap_points: for point in snap_points:
point["group"] = "Object" point["group"] = "Object"
detected_snaps.append(point) detected_snaps.append(point)
else:
snap_point = {
"point": hit,
"type": "Face",
"group": "Object",
"object": snap_obj,
"face_index": face_index,
"distance": 10, # High value so it has low priority
}
detected_snaps.append(snap_point)
# Axis and Plane # Axis and Plane
if tool.Ifc.get(): if tool.Ifc.get():
@@ -536,7 +550,7 @@ class Snap(bonsai.core.tool.Snap):
return filtered_points return filtered_points
def filter_snapping_points_by_group(detected_snaps): def filter_snapping_points_by_group(detected_snaps):
options = ["Edge-Vertex", "Axis", "Plane"] options = ["Wireframe", "Axis", "Plane"]
props = context.scene.BIMSnapGroups props = context.scene.BIMSnapGroups
for prop in props.__annotations__.keys(): for prop in props.__annotations__.keys():
if getattr(props, prop): if getattr(props, prop):
@@ -560,7 +574,7 @@ class Snap(bonsai.core.tool.Snap):
snaps_by_group = filter_snapping_points_by_group(detected_snaps) snaps_by_group = filter_snapping_points_by_group(detected_snaps)
edges = [] # Get edges to create edge-intersection snap edges = [] # Get edges to create edge-intersection snap
for snapping_point in snaps_by_group: for snapping_point in snaps_by_group:
if snapping_point["group"] in {"Polyline", "Measure", "Edge-Vertex", "Object"}: if snapping_point["group"] in {"Polyline", "Measure", "Wireframe", "Object"}:
if snapping_point["type"] == "Edge": if snapping_point["type"] == "Edge":
edges.append(snapping_point) edges.append(snapping_point)
if snapping_point["group"] == "Axis": if snapping_point["group"] == "Axis":