diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index c30bbca3db..c2145b16fb 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -1129,7 +1129,6 @@ class IfcImporter: tool.Aggregate.constrain_all_parts_to_aggregate(relating_obj) bpy.context.scene.BIMAggregateProperties.aggregate_decorator = True - def lock_scales(self) -> None: elements = set(self.file.by_type("IfcProduct")) while elements: diff --git a/src/bonsai/bonsai/bim/module/aggregate/decorator.py b/src/bonsai/bonsai/bim/module/aggregate/decorator.py index 911fc86890..e1afe6b507 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/decorator.py +++ b/src/bonsai/bonsai/bim/module/aggregate/decorator.py @@ -207,7 +207,6 @@ class AggregateDecorator: parts = ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(aggregate)) parts_objs = [tool.Ifc.get_object(p) for p in parts] - indices, edges = create_bounding_box(parts_objs) self.line_shader.uniform_float("lineWidth", 0.5) self.draw_batch("LINES", indices, color, edges) @@ -230,9 +229,7 @@ class AggregateModeDecorator: cls.handlers.append( SpaceView3D.draw_handler_add(handler.draw_aggregate_empty, (context,), "WINDOW", "POST_VIEW") ) - cls.handlers.append( - SpaceView3D.draw_handler_add(handler.draw_new_objects, (context,), "WINDOW", "POST_VIEW") - ) + cls.handlers.append(SpaceView3D.draw_handler_add(handler.draw_new_objects, (context,), "WINDOW", "POST_VIEW")) cls.is_installed = True @classmethod @@ -352,12 +349,11 @@ class AggregateModeDecorator: new_objs = [o for o in new_objs if o.data] for obj in new_objs: element = tool.Ifc.get_entity(obj) - if (aggregate := ifcopenshell.util.element.get_aggregate(element)) == tool.Ifc.get_entity(props.editing_aggregate): + if (aggregate := ifcopenshell.util.element.get_aggregate(element)) == tool.Ifc.get_entity( + props.editing_aggregate + ): continue if element and element.is_a("IfcElement"): data = ItemDecorator.get_obj_data(obj) if data: - self.draw_batch( - "TRIS", data["verts"], transparent_color((1, 0, 0, 1)), data["tris"] - ) - + self.draw_batch("TRIS", data["verts"], transparent_color((1, 0, 0, 1)), data["tris"]) diff --git a/src/bonsai/bonsai/bim/module/aggregate/operator.py b/src/bonsai/bonsai/bim/module/aggregate/operator.py index 87b46412b7..49516d1f82 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/operator.py +++ b/src/bonsai/bonsai/bim/module/aggregate/operator.py @@ -375,6 +375,7 @@ class BIM_OT_select_linked_aggregates(bpy.types.Operator): return {"FINISHED"} + class BIM_OT_disable_aggregate_mode(bpy.types.Operator): bl_idname = "bim.disable_aggregate_mode" bl_label = "Disable Aggregate Mode" @@ -385,6 +386,7 @@ class BIM_OT_disable_aggregate_mode(bpy.types.Operator): bonsai.core.aggregate.disable_aggregate_mode(tool.Aggregate) return {"FINISHED"} + class BIM_OT_toggle_aggregate_mode_local_view(bpy.types.Operator): bl_idname = "bim.toggle_aggregate_mode_local_view" bl_label = "Toggle Aggregate Mode Local View" @@ -403,6 +405,7 @@ class BIM_OT_toggle_aggregate_mode_local_view(bpy.types.Operator): return {"FINISHED"} + class BIM_OT_aggregate_assign_new_objects_in_aggregate_mode(bpy.types.Operator): bl_idname = "bim.aggregate_assign_new_objects_in_aggregate_mode" bl_label = "Aggregate Assign New Objects In Aggregate Mode" @@ -424,7 +427,9 @@ class BIM_OT_aggregate_assign_new_objects_in_aggregate_mode(bpy.types.Operator): new_objs = [o for o in new_objs if o.data] for obj in new_objs: element = tool.Ifc.get_entity(obj) - if (aggregate := ifcopenshell.util.element.get_aggregate(element)) == tool.Ifc.get_entity(props.editing_aggregate): + if (aggregate := ifcopenshell.util.element.get_aggregate(element)) == tool.Ifc.get_entity( + props.editing_aggregate + ): continue if element and element.is_a("IfcElement"): obj.select_set(True) @@ -439,4 +444,3 @@ class BIM_OT_aggregate_assign_new_objects_in_aggregate_mode(bpy.types.Operator): BIM_OT_aggregate_assign_object._execute(self, context) return {"FINISHED"} - diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index 9208ba302a..aac604fb48 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -1858,7 +1858,7 @@ class OverrideEscape(bpy.types.Operator): bpy.ops.bim.hide_all_openings() elif context.scene.BIMAggregateProperties.in_aggregate_mode: bpy.ops.bim.disable_aggregate_mode() - elif active_object:=context.active_object: + elif active_object := context.active_object: if tool.Blender.Modifier.try_canceling_editing_modifier_parameters_or_path(active_object): pass return {"FINISHED"} @@ -1902,7 +1902,9 @@ class OverrideModeSetEdit(bpy.types.Operator, tool.Ifc.Operator): self.report({"ERROR"}, f"Element '{obj.name}' is in item mode and cannot be edited directly") elif obj in [o.obj for o in context.scene.BIMAggregateProperties.not_editing_objects]: obj.select_set(False) - self.report({"ERROR"}, f"Element '{obj.name}' does not belong to this aggregate and cannot be edited directly") + self.report( + {"ERROR"}, f"Element '{obj.name}' does not belong to this aggregate and cannot be edited directly" + ) elif obj in bpy.context.scene.BIMProjectProperties.clipping_planes_objs: self.report({"ERROR"}, "Clipping planes cannot be edited") elif element: diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index a11bd6efff..0d1bd6079e 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -25,7 +25,7 @@ import bmesh import ifcopenshell import bonsai.tool as tool import math -from math import sin, cos, radians +from math import sin, cos, radians from bpy.types import SpaceView3D from bpy_extras import view3d_utils from mathutils import Vector, Matrix @@ -785,7 +785,7 @@ class ProductDecorator: @classmethod def uninstall(cls): - props = bpy.context.scene.BIMProductPreviewProperties # updated by model/polyline.py + props = bpy.context.scene.BIMProductPreviewProperties # updated by model/polyline.py props.verts.clear() props.edges.clear() props.tris.clear() @@ -806,7 +806,7 @@ class ProductDecorator: props = context.scene.BIMProductPreviewProperties data = {} data["verts"] = [(*v.value_3d,) for v in props.verts] - data["edges"] = [(int(e.value_2d[0]),int(e.value_2d[1])) for e in props.edges] + data["edges"] = [(int(e.value_2d[0]), int(e.value_2d[1])) for e in props.edges] data["tris"] = [(int(t.value_3d[0]), int(t.value_3d[1]), int(t.value_3d[2])) for t in props.tris] return data diff --git a/src/bonsai/bonsai/bim/module/model/polyline.py b/src/bonsai/bonsai/bim/module/model/polyline.py index fbaa088003..85ff369a43 100644 --- a/src/bonsai/bonsai/bim/module/model/polyline.py +++ b/src/bonsai/bonsai/bim/module/model/polyline.py @@ -200,6 +200,7 @@ def get_wall_preview_data(context, relating_type): return data + def get_vertical_profile_preview_data(context, relating_type): material = ifcopenshell.util.element.get_material(relating_type) try: @@ -261,7 +262,7 @@ def get_vertical_profile_preview_data(context, relating_type): # Create extrusion bmesh bm = bmesh.new() - grouped_verts.append(grouped_verts[0]) # Close profile + grouped_verts.append(grouped_verts[0]) # Close profile new_verts = [bm.verts.new(v) for v in grouped_verts] new_edges = [bm.edges.new((new_verts[i], new_verts[i + 1])) for i in range(len(grouped_verts) - 1)] @@ -296,11 +297,13 @@ def get_vertical_profile_preview_data(context, relating_type): # Add only profile edges edges = [] for edge in bm.edges: - if (edge.verts[0].co.z == min_z and edge.verts[1].co.z == min_z) or (edge.verts[0].co.z == max_z and edge.verts[1].co.z == max_z): + if (edge.verts[0].co.z == min_z and edge.verts[1].co.z == min_z) or ( + edge.verts[0].co.z == max_z and edge.verts[1].co.z == max_z + ): edges.append(edge) # Add axis edge edges = [(edge.verts[0].index, edge.verts[1].index) for edge in edges] - edges.append((len(verts)-1, len(verts)-2)) + edges.append((len(verts) - 1, len(verts) - 2)) data["verts"] = verts data["edges"] = edges data["tris"] = tris @@ -327,7 +330,7 @@ def get_horizontal_profile_preview_data(context, relating_type): return for point in polyline_points: polyline_verts.append(Vector((point.x, point.y, point.z))) - polyline_edges = [(i, i+1) for i in range(len(polyline_verts)-1)] + polyline_edges = [(i, i + 1) for i in range(len(polyline_verts) - 1)] # Get profile shape settings = ifcopenshell.geom.settings() @@ -372,26 +375,25 @@ def get_horizontal_profile_preview_data(context, relating_type): case "9": grouped_verts = [(v[0] + x_offset, v[1] - y_offset, v[2]) for v in grouped_verts] - # Create profile curve scale_mat = Matrix.Scale(-1, 4, (1.0, 0.0, 0.0)) grouped_verts = [scale_mat @ Vector(v) for v in grouped_verts] - profile_curve = bpy.data.curves.new("Profile", type='CURVE') + profile_curve = bpy.data.curves.new("Profile", type="CURVE") profile_curve.dimensions = "2D" - profile_curve.splines.new('POLY') + profile_curve.splines.new("POLY") profile_curve.splines[0].points.add(len(grouped_verts)) for i, point in enumerate(profile_curve.splines[0].points): - if i == len(grouped_verts): # Close curve + if i == len(grouped_verts): # Close curve point.co = Vector((*grouped_verts[0], 0)) continue point.co = Vector((*grouped_verts[i], 0)) profile_obj = bpy.data.objects.new("Profile", profile_curve) # Create path curve with profile object as bevel - path_curve = bpy.data.curves.new("Polyline", type='CURVE') + path_curve = bpy.data.curves.new("Polyline", type="CURVE") path_curve.dimensions = "2D" - path_curve.splines.new('POLY') + path_curve.splines.new("POLY") path_curve.splines[0].points.add(len(polyline_verts) - 1) for i, point in enumerate(path_curve.splines[0].points): point.co = Vector((*polyline_verts[i], 0)) @@ -400,12 +402,12 @@ def get_horizontal_profile_preview_data(context, relating_type): path_curve.bevel_object = profile_obj # Convert path curve to mesh - # This operation throws a warning when done during gpu drawing, so it was removed from the decorator file to be handled here + # This operation throws a warning when done during gpu drawing, so it was removed from the decorator file to be handled here path_obj = bpy.data.objects.new("Preview", path_curve) context.scene.collection.objects.link(path_obj) bpy.context.view_layer.objects.active = path_obj dg = context.evaluated_depsgraph_get() - path_obj = path_obj.evaluated_get(dg) + path_obj = path_obj.evaluated_get(dg) me = path_obj.to_mesh() # Create bmesh from path mesh @@ -812,13 +814,9 @@ class PolylineOperator: tool.Blender.update_viewport() def get_product_preview_data(self, context: bpy.types.Context, relating_type: ifcopenshell.entity_isntance): - if ( - tool.Model.get_usage_type(relating_type) == "PROFILE" and relating_type.is_a() not in {"IfcColumnType"} - ): + if tool.Model.get_usage_type(relating_type) == "PROFILE" and relating_type.is_a() not in {"IfcColumnType"}: data = get_horizontal_profile_preview_data(context, relating_type) - elif ( - tool.Model.get_usage_type(relating_type) == "PROFILE" and relating_type.is_a() in {"IfcColumnType"} - ): + elif tool.Model.get_usage_type(relating_type) == "PROFILE" and relating_type.is_a() in {"IfcColumnType"}: data = get_vertical_profile_preview_data(context, relating_type) elif tool.Model.get_usage_type(relating_type) == "LAYER2": data = get_wall_preview_data(context, relating_type) @@ -832,7 +830,7 @@ class PolylineOperator: props.verts.clear() props.edges.clear() props.tris.clear() - + for vert in data["verts"]: v = props.verts.add() v.value_3d = vert diff --git a/src/bonsai/bonsai/bim/module/model/profile.py b/src/bonsai/bonsai/bim/module/model/profile.py index e9057b63f7..0d0bfc0227 100644 --- a/src/bonsai/bonsai/bim/module/model/profile.py +++ b/src/bonsai/bonsai/bim/module/model/profile.py @@ -1145,7 +1145,6 @@ class DrawPolylineProfile(bpy.types.Operator, PolylineOperator): for profile1, profile2 in zip(profiles[:-1], profiles[1:]): DumbProfileJoiner().join_V(profile2["obj"], profile1["obj"]) - def modal(self, context, event): if not self.relating_type: self.report({"WARNING"}, "You need to select a profile type.") @@ -1176,7 +1175,6 @@ class DrawPolylineProfile(bpy.types.Operator, PolylineOperator): size = len(items) context.scene.BIMModelProperties.offset_type = items[((index + 1) % size)] - props = bpy.context.scene.BIMModelProperties wall_config = f"""Direction: {props.direction_sense} Offset Type: {props.offset_type} @@ -1222,4 +1220,3 @@ class DrawPolylineProfile(bpy.types.Operator, PolylineOperator): self.tool_state.use_default_container = True self.tool_state.plane_method = "XY" return {"RUNNING_MODAL"} - diff --git a/src/bonsai/bonsai/bim/module/model/prop.py b/src/bonsai/bonsai/bim/module/model/prop.py index bda91f79f3..4c972c657b 100644 --- a/src/bonsai/bonsai/bim/module/model/prop.py +++ b/src/bonsai/bonsai/bim/module/model/prop.py @@ -821,12 +821,13 @@ class BIMPolylineProperties(PropertyGroup): insertion_polyline: bpy.props.CollectionProperty(type=Polyline) measurement_polyline: bpy.props.CollectionProperty(type=Polyline) + class ProductPreviewItem(PropertyGroup): value_3d: bpy.props.FloatVectorProperty() value_2d: bpy.props.FloatVectorProperty(size=2) + class BIMProductPreviewProperties(PropertyGroup): verts: bpy.props.CollectionProperty(type=ProductPreviewItem) edges: bpy.props.CollectionProperty(type=ProductPreviewItem) tris: bpy.props.CollectionProperty(type=ProductPreviewItem) - diff --git a/src/bonsai/bonsai/bim/module/model/workspace.py b/src/bonsai/bonsai/bim/module/model/workspace.py index 87f0602889..dbfd571803 100644 --- a/src/bonsai/bonsai/bim/module/model/workspace.py +++ b/src/bonsai/bonsai/bim/module/model/workspace.py @@ -591,7 +591,7 @@ class EditObjectUI: op = row.operator("bim.disable_aggregate_mode", text="", icon="X") op = row.operator("bim.toggle_aggregate_mode_local_view", text="", icon="ZOOM_SELECTED") op = row.operator("bim.aggregate_assign_new_objects_in_aggregate_mode", text="", icon="CUBE") - + text = format_ifc_camel_case(AuthoringData.data["active_class"]) layout.label(text=f"{text} Edit Tools:", icon="RESTRICT_SELECT_OFF") cls.draw_parameter_adjustments(context) @@ -954,7 +954,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): def hotkey_S_A(self): props = bpy.context.scene.BIMModelProperties relating_type_id = AuthoringData.data["relating_type_id_current"] - relating_type_class = AuthoringData.data["ifc_class_current"] + relating_type_class = AuthoringData.data["ifc_class_current"] if relating_type_id is None: self.report({"ERROR"}, "No relating type selected") return @@ -993,7 +993,9 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): ): bpy.ops.bim.draw_polyline_slab("INVOKE_DEFAULT") elif ( - relating_type_id and tool.Model.get_usage_type(tool.Ifc.get().by_id(int(relating_type_id))) == "PROFILE" and relating_type_class not in {"IfcColumnType"} + relating_type_id + and tool.Model.get_usage_type(tool.Ifc.get().by_id(int(relating_type_id))) == "PROFILE" + and relating_type_class not in {"IfcColumnType"} ): bpy.ops.bim.draw_polyline_profile("INVOKE_DEFAULT") else: diff --git a/src/bonsai/bonsai/bim/module/pset/ui.py b/src/bonsai/bonsai/bim/module/pset/ui.py index 98839b66c3..119d4c2c83 100644 --- a/src/bonsai/bonsai/bim/module/pset/ui.py +++ b/src/bonsai/bonsai/bim/module/pset/ui.py @@ -197,7 +197,9 @@ def draw_psetqto_ui( row = box.row(align=True) row.scale_y = 0.8 row.label(text=prop["Name"]) - op = row.operator("bim.select_similar", text=get_display_value(nominal_value), icon="NONE", emboss=False) + op = row.operator( + "bim.select_similar", text=get_display_value(nominal_value), icon="NONE", emboss=False + ) op.key = '"' + pset["Name"].replace('"', '\\"') + '"."' + prop["Name"].replace('"', '\\"') + '"' # calculate sum of all selected objects if active_operator: diff --git a/src/bonsai/bonsai/bim/ui.py b/src/bonsai/bonsai/bim/ui.py index 69731dfdb9..88bcddcc09 100644 --- a/src/bonsai/bonsai/bim/ui.py +++ b/src/bonsai/bonsai/bim/ui.py @@ -246,9 +246,10 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): ) should_play_chaching_sound: BoolProperty(name="Play A Cha-Ching Sound When Project Costs Updates", default=False) spatial_elements_unselectable: BoolProperty( - name="Make Spatial Elements Unselectable By Default", - default=True, - description="If disabled, it will be possible to select spatial elements in the 3D viewport.\nIt is recommended to keep this `Enabled`, as this can have unintended consequences") + name="Make Spatial Elements Unselectable By Default", + default=True, + description="If disabled, it will be possible to select spatial elements in the 3D viewport.\nIt is recommended to keep this `Enabled`, as this can have unintended consequences", + ) decorations_colour: bpy.props.FloatVectorProperty( name="Decorations Color", subtype="COLOR", default=(1, 1, 1, 1), min=0.0, max=1.0, size=4 ) @@ -1191,15 +1192,16 @@ def draw_custom_context_menu(self: bpy.types.Menu, context: bpy.types.Context) - url_op = layout.operator("bim.open_uri", icon="URL", text="Online IFC Documentation") url_op.uri = url + class BIM_PT_decorators_overlay(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'HEADER' - bl_parent_id = 'VIEW3D_PT_overlay' + bl_space_type = "VIEW_3D" + bl_region_type = "HEADER" + bl_parent_id = "VIEW3D_PT_overlay" bl_label = "Bonsai Decorators" @classmethod def poll(cls, context): - return context.mode == 'OBJECT' + return context.mode == "OBJECT" def draw(self, context): layout = self.layout diff --git a/src/bonsai/bonsai/core/aggregate.py b/src/bonsai/bonsai/core/aggregate.py index 30e2c14965..693063b602 100644 --- a/src/bonsai/bonsai/core/aggregate.py +++ b/src/bonsai/bonsai/core/aggregate.py @@ -86,12 +86,17 @@ def add_part_to_object( assign_object(ifc, aggregator, collector, relating_obj=obj, related_obj=part_obj) blender.set_active_object(obj) -def enable_aggregate_mode(aggregator: tool.Aggregate, obj: bpy.types.Object,): + +def enable_aggregate_mode( + aggregator: tool.Aggregate, + obj: bpy.types.Object, +): if aggregator.get_aggregate_mode(): disable_aggregate_mode(aggregator) aggregator.enable_aggregate_mode(obj) + def disable_aggregate_mode(aggregator: tool.Aggregate): aggregator.disable_aggregate_mode() diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index 5a49c948cd..faf228e286 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -1795,9 +1795,7 @@ class Geometry(bonsai.core.tool.Geometry): return False @classmethod - def get_bvh_tree(cls, obj:bpy.types.Object) -> BVHTree: + def get_bvh_tree(cls, obj: bpy.types.Object) -> BVHTree: bm = tool.Blender.get_bmesh_for_mesh(obj.data) bm.transform(obj.matrix_world) return BVHTree.FromBMesh(bm) - - \ No newline at end of file diff --git a/src/bonsai/bonsai/tool/loader.py b/src/bonsai/bonsai/tool/loader.py index 568bb7899b..6f9b8c84a5 100644 --- a/src/bonsai/bonsai/tool/loader.py +++ b/src/bonsai/bonsai/tool/loader.py @@ -983,8 +983,7 @@ class Loader(bonsai.core.tool.Loader): tool.Loader.load_indexed_colour_map(rep, mesh) ios_edges_values = [ - (e.vertices[0], e.vertices[1]) in ios_edges - or (e.vertices[1], e.vertices[0]) in ios_edges + (e.vertices[0], e.vertices[1]) in ios_edges or (e.vertices[1], e.vertices[0]) in ios_edges for e in mesh.edges ] tool.Blender.Attribute.fill_attribute(mesh, "ios_edges", "EDGE", "BOOLEAN", ios_edges_values) diff --git a/src/bonsai/bonsai/tool/raycast.py b/src/bonsai/bonsai/tool/raycast.py index 5c3d01ecea..4b2d16c4ea 100644 --- a/src/bonsai/bonsai/tool/raycast.py +++ b/src/bonsai/bonsai/tool/raycast.py @@ -206,7 +206,7 @@ class Raycast(bonsai.core.tool.Raycast): bm.free() snapping_points = [] - sorted_points = sorted(points, key=lambda x : x[0]) + sorted_points = sorted(points, key=lambda x: x[0]) for p in sorted_points: point = copy.deepcopy(p) snapping_points.append(point[1]) diff --git a/src/bonsai/bonsai/tool/root.py b/src/bonsai/bonsai/tool/root.py index a19bb227f5..ab5f0a6fc8 100644 --- a/src/bonsai/bonsai/tool/root.py +++ b/src/bonsai/bonsai/tool/root.py @@ -354,7 +354,6 @@ class Root(bonsai.core.tool.Root): tool.Aggregate.constrain_all_parts_to_aggregate(tool.Ifc.get_object(new_aggregate[0])) tool.Blender.select_and_activate_single_object(bpy.context, tool.Ifc.get_object(new_aggregate[0])) - @classmethod def run_geometry_add_representation( cls,