Fix #3069. (Again) review all occurrences of users_collection and collection.name

This commit is contained in:
Dion Moult
2023-06-05 15:11:19 +10:00
parent d030582fbb
commit 1f43ec8709
15 changed files with 76 additions and 84 deletions
@@ -45,7 +45,7 @@ class Annotator:
font.name = "OpenGost Type B TT" font.name = "OpenGost Type B TT"
obj.data.font = font obj.data.font = font
obj.data.BIMTextProperties.font_size = "2.5" obj.data.BIMTextProperties.font_size = "2.5"
collection = bpy.context.scene.camera.users_collection[0] collection = bpy.context.scene.camera.BIMObjectProperties.collection
collection.objects.link(obj) collection.objects.link(obj)
Annotator.resize_text(obj) Annotator.resize_text(obj)
return obj return obj
@@ -53,9 +53,10 @@ class Annotator:
@staticmethod @staticmethod
def resize_text(text_obj): def resize_text(text_obj):
camera = None camera = None
for obj in text_obj.users_collection[0].objects: group = tool.Drawing.get_drawing_group(tool.Ifc.get_entity(text_obj))
if isinstance(obj.data, bpy.types.Camera): for element in tool.Drawing.get_drawing_elements(group):
camera = obj if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
camera = tool.Ifc.get_object(element)
break break
if not camera: if not camera:
return return
@@ -112,7 +113,7 @@ class Annotator:
co1, _, _, _ = Annotator.get_placeholder_coords(camera) co1, _, _, _ = Annotator.get_placeholder_coords(camera)
matrix_world = camera.matrix_world.copy() matrix_world = camera.matrix_world.copy()
matrix_world.translation = co1 matrix_world.translation = co1
collection = camera.users_collection[0] collection = camera.BIMObjectProperties.collection
if object_type == "TEXT": if object_type == "TEXT":
obj = bpy.data.objects.new(object_type, None) obj = bpy.data.objects.new(object_type, None)
@@ -269,7 +269,7 @@ def get_active_drawing(scene):
props = scene.DocProperties props = scene.DocProperties
try: try:
camera = tool.Ifc.get_object(tool.Ifc.get().by_id(props.active_drawing_id)) camera = tool.Ifc.get_object(tool.Ifc.get().by_id(props.active_drawing_id))
return camera.users_collection[0], camera return camera.BIMObjectProperties.collection, camera
except: except:
return None, None return None, None
@@ -288,7 +288,7 @@ class CreateDrawing(bpy.types.Operator):
bpy.ops.render.render(write_still=True) bpy.ops.render.render(write_still=True)
else: else:
previous_visibility = {} previous_visibility = {}
for obj in self.camera.users_collection[0].objects: for obj in self.camera.BIMObjectProperties.collection.objects:
if bpy.context.view_layer.objects.get(obj.name): if bpy.context.view_layer.objects.get(obj.name):
previous_visibility[obj.name] = obj.hide_get() previous_visibility[obj.name] = obj.hide_get()
obj.hide_set(True) obj.hide_set(True)
@@ -1350,7 +1350,7 @@ class ResizeText(bpy.types.Operator):
# TODO: check undo redo # TODO: check undo redo
def execute(self, context): def execute(self, context):
for obj in context.scene.camera.users_collection[0].objects: for obj in context.scene.camera.BIMObjectProperties.collection.objects:
if isinstance(obj.data, bpy.types.TextCurve): if isinstance(obj.data, bpy.types.TextCurve):
annotation.Annotator.resize_text(obj) annotation.Annotator.resize_text(obj)
return {"FINISHED"} return {"FINISHED"}
@@ -231,7 +231,7 @@ def toggleDecorations(self, context):
toggle = self.should_draw_decorations toggle = self.should_draw_decorations
if toggle: if toggle:
# TODO: design a proper text variable templating renderer # TODO: design a proper text variable templating renderer
collection = context.scene.camera.users_collection[0] collection = context.scene.camera.BIMObjectProperties.collection
for obj in collection.objects: for obj in collection.objects:
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
if not element or not tool.Drawing.is_annotation_object_type(element, ["TEXT", "TEXT_LEADER"]): if not element or not tool.Drawing.is_annotation_object_type(element, ["TEXT", "TEXT_LEADER"]):
@@ -68,7 +68,7 @@ class PieUpdateContainer(bpy.types.Operator):
if not obj.BIMObjectProperties.ifc_definition_id: if not obj.BIMObjectProperties.ifc_definition_id:
continue continue
for collection in obj.users_collection: for collection in obj.users_collection:
spatial_obj = bpy.data.objects.get(collection.name) spatial_obj = collection.BIMCollectionProperties.obj
if spatial_obj and spatial_obj.BIMObjectProperties.ifc_definition_id: if spatial_obj and spatial_obj.BIMObjectProperties.ifc_definition_id:
blenderbim.core.spatial.assign_container( blenderbim.core.spatial.assign_container(
tool.Ifc, tool.Collector, tool.Spatial, structure_obj=spatial_obj, element_obj=obj tool.Ifc, tool.Collector, tool.Spatial, structure_obj=spatial_obj, element_obj=obj
@@ -128,20 +128,9 @@ class AddConstrTypeInstance(bpy.types.Operator):
obj.location = context.scene.cursor.location obj.location = context.scene.cursor.location
collection = None collection = context.view_layer.active_layer_collection.collection
if (
building_obj
and building_element
and building_element.is_a() in ["IfcWall", "IfcWallStandardCase", "IfcCovering"]
and instance_class in ["IfcWindow", "IfcDoor"]
):
# Fills should be a sibling to the building element
collection = building_obj.users_collection[0]
if not collection:
collection = context.view_layer.active_layer_collection.collection
collection.objects.link(obj) collection.objects.link(obj)
collection_obj = bpy.data.objects.get(collection.name) collection_obj = collection.BIMCollectionProperties.obj
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class) bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class)
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
@@ -150,6 +139,26 @@ class AddConstrTypeInstance(bpy.types.Operator):
# Update required as core.type.assign_type may change obj.data # Update required as core.type.assign_type may change obj.data
context.view_layer.update() context.view_layer.update()
if (
building_obj
and building_element
and building_element.is_a() in ["IfcWall", "IfcWallStandardCase", "IfcCovering"]
and instance_class in ["IfcWindow", "IfcDoor"]
):
# Fills should be a sibling to the building element
parent = ifcopenshell.util.element.get_aggregate(building_element)
if parent:
parent_obj = tool.Ifc.get_object(parent)
blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=parent_obj, related_obj=obj
)
else:
parent = ifcopenshell.util.element.get_container(building_element)
parent_obj = tool.Ifc.get_object(parent)
blenderbim.core.spatial.assign_container(
tool.Ifc, tool.Collector, tool.Spatial, structure_obj=parent_obj, element_obj=obj
)
# set occurences properties for the types defined with modifiers # set occurences properties for the types defined with modifiers
if instance_class in ["IfcWindow", "IfcDoor"]: if instance_class in ["IfcWindow", "IfcDoor"]:
pset_name = f"BBIM_{instance_class[3:]}" pset_name = f"BBIM_{instance_class[3:]}"
@@ -462,11 +471,6 @@ class MirrorElements(bpy.types.Operator, tool.Ifc.Operator):
obj.matrix_world = newmat obj.matrix_world = newmat
def copy_obj(self, obj):
new = obj.copy()
new.data = wall2.data.copy()
wall1.users_collection[0].objects.link(wall2)
blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=wall2)
def generate_box(usecase_path, ifc_file, settings): def generate_box(usecase_path, ifc_file, settings):
@@ -53,7 +53,7 @@ class DumbProfileGenerator:
self.axis_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Axis", "GRAPH_VIEW") self.axis_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Axis", "GRAPH_VIEW")
props = bpy.context.scene.BIMModelProperties props = bpy.context.scene.BIMModelProperties
self.collection = bpy.context.view_layer.active_layer_collection.collection self.collection = bpy.context.view_layer.active_layer_collection.collection
self.collection_obj = bpy.data.objects.get(self.collection.name) self.collection_obj = self.collection.BIMCollectionProperties.obj
self.depth = props.extrusion_depth self.depth = props.extrusion_depth
self.rotation = 0 self.rotation = 0
self.location = Vector((0, 0, 0)) self.location = Vector((0, 0, 0))
@@ -133,7 +133,7 @@ class DumbSlabGenerator:
props = bpy.context.scene.BIMModelProperties props = bpy.context.scene.BIMModelProperties
self.collection = bpy.context.view_layer.active_layer_collection.collection self.collection = bpy.context.view_layer.active_layer_collection.collection
self.collection_obj = bpy.data.objects.get(self.collection.name) self.collection_obj = self.collection.BIMCollectionProperties.obj
self.depth = sum(thicknesses) * unit_scale self.depth = sum(thicknesses) * unit_scale
self.width = 3 self.width = 3
self.length = 3 self.length = 3
@@ -38,7 +38,7 @@ class GenerateSpace(bpy.types.Operator, tool.Ifc.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
collection = context.view_layer.active_layer_collection.collection collection = context.view_layer.active_layer_collection.collection
collection_obj = bpy.data.objects.get(collection.name) collection_obj = collection.BIMCollectionProperties.obj
return tool.Ifc.get_entity(collection_obj) return tool.Ifc.get_entity(collection_obj)
def _execute(self, context): def _execute(self, context):
@@ -60,7 +60,7 @@ class GenerateSpace(bpy.types.Operator, tool.Ifc.Operator):
relating_type = None relating_type = None
collection = context.view_layer.active_layer_collection.collection collection = context.view_layer.active_layer_collection.collection
collection_obj = bpy.data.objects.get(collection.name) collection_obj = collection.BIMCollectionProperties.obj
if not collection_obj: if not collection_obj:
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR") bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
return return
@@ -203,29 +203,19 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
active_obj = bpy.context.active_object active_obj = bpy.context.active_object
if not active_obj: if not active_obj:
self.report({'ERROR'}, "No active object. Please select a wall") self.report({"ERROR"}, "No active object. Please select a wall")
return return
element = None
element = tool.Ifc.get_entity(active_obj) element = tool.Ifc.get_entity(active_obj)
if element: if element and not element.is_a("IfcWall"):
if not element.is_a("IfcWall"): return self.report({"ERROR"}, "The active object is not a wall. Please select a wall.")
self.report({'ERROR'}, "The active object is not a wall. Please select a wall.")
return
collection = active_obj.users_collection[0] container = ifcopenshell.util.element.get_container(element)
collection_obj = bpy.data.objects.get(collection.name) if not container:
if not collection_obj: self.report({"ERROR"}, "The wall is not contained.")
self.report({'ERROR'}, "No collection found. Please insert one.")
return
spatial_element = tool.Ifc.get_entity(collection_obj)
if not spatial_element:
self.report({'ERROR'}, "The collection hasn't an ifc space entity. Please provide one.")
return
if not bpy.context.selected_objects: if not bpy.context.selected_objects:
self.report({'ERROR'}, "No selected objects found. Please select walls.") self.report({"ERROR"}, "No selected objects found. Please select walls.")
return return
x, y, z = active_obj.matrix_world.translation.xyz x, y, z = active_obj.matrix_world.translation.xyz
@@ -237,19 +227,18 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
polys = self.get_polygons(boundary_elements) polys = self.get_polygons(boundary_elements)
converted_tolerance = self.get_converted_tolerance(tolerance = 0.03) converted_tolerance = self.get_converted_tolerance(tolerance=0.03)
union = shapely.ops.unary_union(polys).buffer(converted_tolerance, cap_style = 2, join_style = 2) union = shapely.ops.unary_union(polys).buffer(converted_tolerance, cap_style=2, join_style=2)
i=0 for i, linear_ring in enumerate(union.interiors):
for linear_ring in union.interiors:
poly = Polygon(linear_ring) poly = Polygon(linear_ring)
poly = poly.buffer(converted_tolerance, single_sided=True, cap_style = 2, join_style = 2) poly = poly.buffer(converted_tolerance, single_sided=True, cap_style=2, join_style=2)
bm = self.get_bmesh_from_polygon(poly, mat, h) bm = self.get_bmesh_from_polygon(poly, mat, h)
name = "Space" + str(i) name = "Space" + str(i)
mesh = bpy.data.meshes.new(name = name) mesh = bpy.data.meshes.new(name=name)
bm.to_mesh(mesh) bm.to_mesh(mesh)
bm.free() bm.free()
@@ -258,13 +247,12 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
self.set_obj_origin_to_bboxcenter(obj) self.set_obj_origin_to_bboxcenter(obj)
collection.objects.link(obj) context.view_layer.active_layer_collection.collection.objects.link(obj)
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcSpace") bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcSpace")
i+=1 container_obj = tool.Ifc.get_object(container)
blenderbim.core.spatial.assign_container(
return {"FINISHED"} tool.Ifc, tool.Collector, tool.Spatial, structure_obj=container_obj, element_obj=obj
)
def get_boundary_elements(self, selected_objects): def get_boundary_elements(self, selected_objects):
boundary_elements = [] boundary_elements = []
@@ -302,15 +290,15 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
def get_converted_tolerance(self, tolerance): def get_converted_tolerance(self, tolerance):
model = tool.Ifc.get() model = tool.Ifc.get()
project_unit = ifcopenshell.util.unit.get_project_unit(model, "LENGTHUNIT") project_unit = ifcopenshell.util.unit.get_project_unit(model, "LENGTHUNIT")
prefix=getattr(project_unit, "Prefix", None) prefix = getattr(project_unit, "Prefix", None)
converted_tolerance = ifcopenshell.util.unit.convert( converted_tolerance = ifcopenshell.util.unit.convert(
value = tolerance, value=tolerance,
from_prefix = None, from_prefix=None,
from_unit = "METRE", from_unit="METRE",
to_prefix = prefix, to_prefix=prefix,
to_unit = project_unit.Name, to_unit=project_unit.Name,
) )
return tolerance return tolerance
def get_bmesh_from_polygon(self, poly, mat, h): def get_bmesh_from_polygon(self, poly, mat, h):
@@ -335,7 +323,7 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
extruded_verts = [g for g in extrusion["geom"] if isinstance(g, bmesh.types.BMVert)] extruded_verts = [g for g in extrusion["geom"] if isinstance(g, bmesh.types.BMVert)]
bmesh.ops.translate(bm, vec=[0.0, 0.0, h], verts=extruded_verts) bmesh.ops.translate(bm, vec=[0.0, 0.0, h], verts=extruded_verts)
bmesh.ops.recalc_face_normals(bm, faces = bm.faces) bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
return bm return bm
@@ -434,7 +434,7 @@ class DumbWallGenerator:
props = bpy.context.scene.BIMModelProperties props = bpy.context.scene.BIMModelProperties
self.collection = bpy.context.view_layer.active_layer_collection.collection self.collection = bpy.context.view_layer.active_layer_collection.collection
self.collection_obj = bpy.data.objects.get(self.collection.name) self.collection_obj = self.collection.BIMCollectionProperties.obj
self.width = self.layers["thickness"] self.width = self.layers["thickness"]
self.height = props.extrusion_depth self.height = props.extrusion_depth
self.length = props.length self.length = props.length
@@ -934,7 +934,8 @@ class DumbWallJoiner:
def duplicate_wall(self, wall1): def duplicate_wall(self, wall1):
wall2 = wall1.copy() wall2 = wall1.copy()
wall2.data = wall2.data.copy() wall2.data = wall2.data.copy()
wall1.users_collection[0].objects.link(wall2) for collection in wall1.users_collection:
collection.objects.link(wall2)
blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=wall2) blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=wall2)
return wall2 return wall2
@@ -371,7 +371,8 @@ class AppendLibraryElement(bpy.types.Operator):
if not type_collection: if not type_collection:
type_collection = bpy.data.collections.new("Types") type_collection = bpy.data.collections.new("Types")
for collection in bpy.context.view_layer.layer_collection.children: for collection in bpy.context.view_layer.layer_collection.children:
if "IfcProject/" in collection.name: collection_obj = collection.BIMCollectionProperties.obj
if collection_obj and tool.Ifc.get_entity(collection_obj).is_a("IfcProject"):
collection.collection.children.link(type_collection) collection.collection.children.link(type_collection)
collection.children["Types"].hide_viewport = True collection.children["Types"].hide_viewport = True
break break
+1 -1
View File
@@ -318,7 +318,7 @@ def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
ifc.run("attribute.edit_attributes", product=group, attributes={"Name": name}) ifc.run("attribute.edit_attributes", product=group, attributes={"Name": name})
collection = drawing_tool.get_drawing_collection(drawing) collection = drawing_tool.get_drawing_collection(drawing)
if collection: if collection:
drawing_tool.set_drawing_collection_name(group, collection) drawing_tool.set_drawing_collection_name(drawing, collection)
reference = drawing_tool.get_drawing_document(drawing) reference = drawing_tool.get_drawing_document(drawing)
information = drawing_tool.get_reference_document(reference) information = drawing_tool.get_reference_document(reference)
+1 -1
View File
@@ -311,7 +311,7 @@ class Drawing:
def run_drawing_activate_model(cls): pass def run_drawing_activate_model(cls): pass
def run_root_assign_class(cls, obj=None, ifc_class=None, predefined_type=None, should_add_representation=True, context=None, ifc_representation_class=None): pass def run_root_assign_class(cls, obj=None, ifc_class=None, predefined_type=None, should_add_representation=True, context=None, ifc_representation_class=None): pass
def select_assigned_product(cls, drawing): pass def select_assigned_product(cls, drawing): pass
def set_drawing_collection_name(cls, group, collection): pass def set_drawing_collection_name(cls, drawing, collection): pass
def set_name(cls, element, name): pass def set_name(cls, element, name): pass
def setup_annotation_object(cls, obj, object_type): pass def setup_annotation_object(cls, obj, object_type): pass
def setup_shading_styles_path(cls, resource_path): pass def setup_shading_styles_path(cls, resource_path): pass
+2 -5
View File
@@ -143,11 +143,8 @@ class Collector(blenderbim.core.tool.Collector):
return axes_col[0] return axes_col[0]
return bpy.data.collections.new(axes) return bpy.data.collections.new(axes)
if element.is_a("IfcAnnotation"): if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
for rel in element.HasAssignments or []: return cls._create_own_collection(obj)
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.ObjectType == "DRAWING":
name = "IfcGroup/" + rel.RelatingGroup.Name
return bpy.data.collections.get(name) or bpy.data.collections.new(name)
if element.is_a("IfcStructuralMember"): if element.is_a("IfcStructuralMember"):
return bpy.data.collections.get("Members") or bpy.data.collections.new("Members") return bpy.data.collections.get("Members") or bpy.data.collections.new("Members")
+5 -5
View File
@@ -364,7 +364,7 @@ class Drawing(blenderbim.core.tool.Drawing):
def get_drawing_collection(cls, drawing): def get_drawing_collection(cls, drawing):
obj = tool.Ifc.get_object(drawing) obj = tool.Ifc.get_object(drawing)
if obj: if obj:
return obj.users_collection[0] return obj.BIMObjectProperties.collection
@classmethod @classmethod
def get_drawing_group(cls, drawing): def get_drawing_group(cls, drawing):
@@ -759,8 +759,8 @@ class Drawing(blenderbim.core.tool.Drawing):
) )
@classmethod @classmethod
def set_drawing_collection_name(cls, group, collection): def set_drawing_collection_name(cls, drawing, collection):
collection.name = f"IfcGroup/{group.Name}" collection.name = tool.Loader.get_name(drawing)
@classmethod @classmethod
def set_name(cls, element, name): def set_name(cls, element, name):
@@ -1486,8 +1486,8 @@ class Drawing(blenderbim.core.tool.Drawing):
project_collection.children["Views"].children[collection.name].hide_viewport = True project_collection.children["Views"].children[collection.name].hide_viewport = True
bpy.data.collections.get(collection.name).hide_render = True bpy.data.collections.get(collection.name).hide_render = True
project_collection.children["Views"].children[camera.users_collection[0].name].hide_viewport = False project_collection.children["Views"].children[camera.BIMObjectProperties.collection.name].hide_viewport = False
bpy.data.collections.get(camera.users_collection[0].name).hide_render = False camera.BIMObjectProperties.collection.hide_render = False
tool.Spatial.set_active_object(camera) tool.Spatial.set_active_object(camera)
# Sync viewport objects visibility with selectors from EPset_Drawing/Include and /Exclude # Sync viewport objects visibility with selectors from EPset_Drawing/Include and /Exclude