This commit is contained in:
Dion Moult
2026-01-15 22:00:51 +11:00
parent 47a2c1d21a
commit 8060c790ed
3 changed files with 18 additions and 16 deletions
@@ -1723,11 +1723,11 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
container=container,
element_obj=obj,
)
# Get the container's collection for moving parts in the outliner
container_obj = tool.Ifc.get_object(container)
container_collection = container_obj.BIMObjectProperties.collection if container_obj else None
# Move all parts to the container's collection in the outliner
if container_collection:
for part in ifcopenshell.util.element.get_parts(element):
@@ -1736,11 +1736,11 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
# Remove from all previous collections
for col in part_obj.users_collection[:]:
col.objects.unlink(part_obj)
# Link to container collection
if part_obj.name not in container_collection.objects:
container_collection.objects.link(part_obj)
# Recursively handle nested parts
for nested_part in ifcopenshell.util.element.get_parts(part):
nested_part_obj = tool.Ifc.get_object(nested_part)
+7 -5
View File
@@ -575,20 +575,22 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
rotation_axis.normalize()
dot_product = expected_new_world_direction.dot(current_world_direction)
angle = acos(min(max(dot_product, -1), 1))
# Rotate around object's own origin
# Decompose the matrix to get translation, rotation, scale
translation, rotation, scale = obj.matrix_world.decompose()
# Create rotation matrix and convert to quaternion
rotation_matrix = Matrix.Rotation(angle, 4, rotation_axis)
rotation_quat = rotation_matrix.to_quaternion()
# Apply rotation to existing rotation (quaternion multiplication)
new_rotation = rotation_quat @ rotation
# Reconstruct matrix_world with same translation, new rotation, same scale
obj.matrix_world = Matrix.Translation(translation) @ new_rotation.to_matrix().to_4x4() @ Matrix.Scale(1, 4)
obj.matrix_world = (
Matrix.Translation(translation) @ new_rotation.to_matrix().to_4x4() @ Matrix.Scale(1, 4)
)
bpy.context.view_layer.update()
bonsai.core.geometry.switch_representation(
@@ -183,7 +183,7 @@ class AssignContainer(bpy.types.Operator, tool.Ifc.Operator):
root = aggregate
current = aggregate
return root
def get_all_parts_recursive(element):
"""Recursively get all parts of an aggregate"""
parts = []
@@ -196,17 +196,17 @@ class AssignContainer(bpy.types.Operator, tool.Ifc.Operator):
objs: list[bpy.types.Object] = []
processed_elements = set() # Track elements we've already handled (by IFC ID)
promoted_parts = 0 # Count how many parts were promoted to their root aggregate
for obj in tool.Blender.get_selected_objects():
if not (element := tool.Ifc.get_entity(obj)):
continue
# Check if element is part of an aggregate (at any level)
if root_aggregate := get_root_aggregate(element):
# Skip if we've already processed this root aggregate
if root_aggregate.id() in processed_elements:
continue
# Get the root aggregate object and add it instead
if root_aggregate_obj := tool.Ifc.get_object(root_aggregate):
objs.append(root_aggregate_obj)
@@ -225,13 +225,13 @@ class AssignContainer(bpy.types.Operator, tool.Ifc.Operator):
for element_obj in objs:
element = tool.Ifc.get_entity(element_obj)
# Only assign container to the ROOT aggregate (this updates IFC relationships)
if self.remove_from_other_containers:
for col in element_obj.users_collection[:]:
col.objects.unlink(element_obj)
core.assign_container(tool.Ifc, tool.Collector, tool.Spatial, container=container, element_obj=element_obj)
# For parts, only move them in Blender collections (don't change IFC relationships)
if container_collection:
all_parts = get_all_parts_recursive(element)
@@ -240,7 +240,7 @@ class AssignContainer(bpy.types.Operator, tool.Ifc.Operator):
# Always remove from ALL previous collections when moving to new container
for col in part_obj.users_collection[:]:
col.objects.unlink(part_obj)
# Link to new container collection (Blender-only, no IFC change)
if part_obj.name not in container_collection.objects:
container_collection.objects.link(part_obj)