mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
Fix issues with snapping empties and faceless objects in x-ray mode.
This commit is contained in:
@@ -328,23 +328,34 @@ 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
|
||||||
return None, None, None
|
face_index = None
|
||||||
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj)
|
# Wireframes
|
||||||
if hit is None:
|
if obj.type in {"EMPTY", "CURVE"} or (hasattr(obj.data, "polygons") and len(obj.data.polygons) == 0) :
|
||||||
# Tried original mouse position. Now it will try the offsets.
|
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, obj)
|
||||||
original_mouse_pos = mouse_pos
|
if snap_points:
|
||||||
for value in mouse_offset:
|
hit = sorted(snap_points, key=lambda x: x["distance"])[0]["point"]
|
||||||
mouse_pos = tuple(x + y for x, y in zip(original_mouse_pos, value))
|
|
||||||
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj, mouse_pos)
|
|
||||||
if hit:
|
if hit:
|
||||||
break
|
hit_world = obj.original.matrix_world @ hit
|
||||||
mouse_pos = original_mouse_pos
|
return obj, hit_world, face_index
|
||||||
if hit:
|
|
||||||
hit_world = obj.original.matrix_world @ hit
|
|
||||||
return obj, hit_world, face_index
|
|
||||||
else:
|
|
||||||
return None, None, None
|
return None, None, None
|
||||||
|
# Meshes
|
||||||
|
else:
|
||||||
|
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj)
|
||||||
|
if hit is None:
|
||||||
|
# Tried original mouse position. Now it will try the offsets.
|
||||||
|
original_mouse_pos = mouse_pos
|
||||||
|
for value in mouse_offset:
|
||||||
|
mouse_pos = tuple(x + y for x, y in zip(original_mouse_pos, value))
|
||||||
|
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj, mouse_pos)
|
||||||
|
if hit:
|
||||||
|
break
|
||||||
|
mouse_pos = original_mouse_pos
|
||||||
|
if hit:
|
||||||
|
hit_world = obj.original.matrix_world @ hit
|
||||||
|
return obj, hit_world, face_index
|
||||||
|
else:
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
def cast_rays_and_get_best_object(
|
def cast_rays_and_get_best_object(
|
||||||
objs_to_raycast: list[bpy.types.Object], mouse_pos: tuple[int, int]
|
objs_to_raycast: list[bpy.types.Object], mouse_pos: tuple[int, int]
|
||||||
@@ -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,29 +428,49 @@ 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:
|
||||||
snap_points = tool.Raycast.ray_cast_by_proximity(
|
# Wireframes
|
||||||
context, event, snap_obj, snap_obj.data.polygons[face_index]
|
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:
|
if snap_points:
|
||||||
for point in snap_points:
|
for point in snap_points:
|
||||||
point["group"] = "Object"
|
point["group"] = "Wireframe"
|
||||||
detected_snaps.append(point)
|
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:
|
else:
|
||||||
|
# Add face snap
|
||||||
snap_point = {
|
snap_point = {
|
||||||
"point": hit,
|
"point": hit,
|
||||||
"type": "Face",
|
"type": "Face",
|
||||||
"group": "Object",
|
"group": "Object",
|
||||||
"object": snap_obj,
|
"object": snap_obj,
|
||||||
"face_index": face_index,
|
"face_index": face_index,
|
||||||
"distance": 10, # High value so it has low priority
|
"distance": 9, # High value so it has low priority
|
||||||
}
|
}
|
||||||
detected_snaps.append(snap_point)
|
detected_snaps.append(snap_point)
|
||||||
|
|
||||||
|
# Add vertex and edge snap
|
||||||
|
snap_points = tool.Raycast.ray_cast_by_proximity(
|
||||||
|
context, event, snap_obj, snap_obj.data.polygons[face_index]
|
||||||
|
)
|
||||||
|
if snap_points:
|
||||||
|
for point in snap_points:
|
||||||
|
point["group"] = "Object"
|
||||||
|
detected_snaps.append(point)
|
||||||
|
|
||||||
# Axis and Plane
|
# Axis and Plane
|
||||||
if tool.Ifc.get():
|
if tool.Ifc.get():
|
||||||
elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
||||||
@@ -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":
|
||||||
|
|||||||
Reference in New Issue
Block a user