This commit is contained in:
Andrej730
2025-07-15 11:19:32 +05:00
parent a461281b1e
commit f18c93c9ee
15 changed files with 65 additions and 44 deletions
@@ -1208,9 +1208,11 @@ class ActivateBcfViewpoint(bpy.types.Operator):
self.file = tool.Ifc.get() self.file = tool.Ifc.get()
bcfxml = bcfstore.BcfStore.get_bcfxml() bcfxml = bcfstore.BcfStore.get_bcfxml()
assert bcfxml assert bcfxml
assert context.scene
props = tool.Bcf.get_bcf_props() props = tool.Bcf.get_bcf_props()
blender_topic = props.active_topic blender_topic = props.active_topic
assert blender_topic
topic = bcfxml.topics[blender_topic.name] topic = bcfxml.topics[blender_topic.name]
if self.viewpoint_guid: if self.viewpoint_guid:
viewpoint_guid = self.viewpoint_guid viewpoint_guid = self.viewpoint_guid
@@ -1234,6 +1236,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
cam_height = context.scene.render.resolution_y cam_height = context.scene.render.resolution_y
cam_aspect = cam_width / cam_height cam_aspect = cam_width / cam_height
assert isinstance(obj.data, bpy.types.Camera)
obj.data.background_images.clear() obj.data.background_images.clear()
if viewpoint.snapshot: if viewpoint.snapshot:
obj.data.show_background_images = True obj.data.show_background_images = True
+1 -1
View File
@@ -48,7 +48,7 @@ class BIM_PT_materials(Panel):
MaterialsData.load() MaterialsData.load()
self.props = tool.Material.get_material_props() self.props = tool.Material.get_material_props()
material = tool.Material.get_active_material_item() material = self.props.active_material
material_id = material.ifc_definition_id if material else None material_id = material.ifc_definition_id if material else None
row = self.layout.row(align=True) row = self.layout.row(align=True)
@@ -371,7 +371,9 @@ def get_vertical_profile_preview_data(
return data return data
def get_horizontal_profile_preview_data(context, relating_type): def get_horizontal_profile_preview_data(
context: bpy.types.Context, relating_type: ifcopenshell.entity_instance
) -> dict[str, Any]:
material = ifcopenshell.util.element.get_material(relating_type) material = ifcopenshell.util.element.get_material(relating_type)
try: try:
profile_curve = material.MaterialProfiles[0].Profile profile_curve = material.MaterialProfiles[0].Profile
@@ -385,7 +387,7 @@ def get_horizontal_profile_preview_data(context, relating_type):
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else [] polyline_points = polyline_data[0].polyline_points if polyline_data else []
if len(polyline_points) < 2: if len(polyline_points) < 2:
return return {}
for point in polyline_points: for point in polyline_points:
polyline_verts.append(Vector((point.x, point.y, point.z))) 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)]
@@ -433,7 +435,7 @@ def get_horizontal_profile_preview_data(context, relating_type):
case "9": case "9":
grouped_verts = [(v[0] + x_offset, v[1] - y_offset, v[2]) for v in grouped_verts] grouped_verts = [(v[0] + x_offset, v[1] - y_offset, v[2]) for v in grouped_verts]
data = {} data: dict[str, Any] = {}
data["verts"] = [] data["verts"] = []
data["edges"] = [] data["edges"] = []
data["tris"] = [] data["tris"] = []
+10 -6
View File
@@ -115,7 +115,7 @@ def get_material_pset_names(self: "PsetProperties", context: object) -> tool.Ble
return MaterialPsetsData.data["pset_name"] return MaterialPsetsData.data["pset_name"]
def get_material_set_pset_names(self: "PsetProperties", context: object): def get_material_set_pset_names(self: "PsetProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
global psetnames global psetnames
if not ObjectMaterialData.is_loaded: if not ObjectMaterialData.is_loaded:
ObjectMaterialData.load() ObjectMaterialData.load()
@@ -128,12 +128,14 @@ def get_material_set_pset_names(self: "PsetProperties", context: object):
return psetnames[ifc_class] return psetnames[ifc_class]
def get_material_set_item_pset_names(self: "PsetProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_material_set_item_pset_names(
self: "PsetProperties", context: bpy.types.Context
) -> tool.Blender.BLENDER_ENUM_ITEMS:
global psetnames global psetnames
obj = context.active_object obj = context.active_object
assert obj assert obj
omprops = tool.Material.get_object_material_props(obj) omprops = tool.Material.get_object_material_props(obj)
if not omprops.active_material_set_item_id: if not (ifc_definition_id := omprops.active_material_set_item_id):
return [] return []
ifc_class = tool.Ifc.get().by_id(ifc_definition_id).is_a() ifc_class = tool.Ifc.get().by_id(ifc_definition_id).is_a()
if ifc_class not in psetnames: if ifc_class not in psetnames:
@@ -151,7 +153,7 @@ def get_task_qto_names(self: "PsetProperties", context: object) -> tool.Blender.
return qtonames[ifc_class] return qtonames[ifc_class]
def get_resource_pset_names(self: "PsetProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_resource_pset_names(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
global psetnames global psetnames
rprops = context.scene.BIMResourceProperties rprops = context.scene.BIMResourceProperties
rtprops = context.scene.BIMResourceTreeProperties rtprops = context.scene.BIMResourceTreeProperties
@@ -162,7 +164,7 @@ def get_resource_pset_names(self: "PsetProperties", context: object) -> tool.Ble
return psetnames[ifc_class] return psetnames[ifc_class]
def get_resource_qto_names(self: "PsetProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_resource_qto_names(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
global qtonames global qtonames
rprops = context.scene.BIMResourceProperties rprops = context.scene.BIMResourceProperties
rtprops = context.scene.BIMResourceTreeProperties rtprops = context.scene.BIMResourceTreeProperties
@@ -223,7 +225,9 @@ def get_qto_name(self: "PsetProperties", context: bpy.types.Context) -> tool.Ble
results = get_resource_qto_names(self, context) results = get_resource_qto_names(self, context)
elif prop_type == "GroupPsetProperties": elif prop_type == "GroupPsetProperties":
results = get_group_qto_names(self, context) results = get_group_qto_names(self, context)
return [("BBIM_CUSTOM", "Custom Qto", "Create a quantity set without using a template."), None] + results else:
assert False
return [("BBIM_CUSTOM", "Custom Qto", "Create a quantity set without using a template."), None] + list(results)
def get_object_qto_name(self: "PsetProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_object_qto_name(self: "PsetProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
+17 -9
View File
@@ -484,7 +484,7 @@ class BIM_PT_material_psets(Panel):
elif ifc_definition_id != MaterialPsetsData.data["ifc_definition_id"]: elif ifc_definition_id != MaterialPsetsData.data["ifc_definition_id"]:
MaterialPsetsData.load() MaterialPsetsData.load()
props = context.scene.MaterialPsetProperties props = tool.Pset.get_pset_props("", "Material")
row = self.layout.row(align=True) row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
@@ -524,6 +524,7 @@ class BIM_PT_material_set_item_psets(Panel):
if not MaterialSetItemPsetsData.is_loaded: if not MaterialSetItemPsetsData.is_loaded:
MaterialSetItemPsetsData.load() MaterialSetItemPsetsData.load()
assert self.layout
obj = context.active_object obj = context.active_object
assert obj assert obj
omprops = tool.Material.get_object_material_props(obj) omprops = tool.Material.get_object_material_props(obj)
@@ -531,7 +532,7 @@ class BIM_PT_material_set_item_psets(Panel):
self.layout.label(text="No Material Set Item Edited.") self.layout.label(text="No Material Set Item Edited.")
return return
props = obj.MaterialSetItemPsetProperties props = tool.Pset.get_pset_props(obj.name, "MaterialSetItem")
row = self.layout.row(align=True) row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
@@ -570,7 +571,8 @@ class BIM_PT_task_qtos(Panel):
if not TaskQtosData.is_loaded: if not TaskQtosData.is_loaded:
TaskQtosData.load() TaskQtosData.load()
props = context.scene.TaskPsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "Task")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(props, "qto_name", text="") row.prop(props, "qto_name", text="")
op = row.operator("bim.add_qto", icon="ADD", text="") op = row.operator("bim.add_qto", icon="ADD", text="")
@@ -604,7 +606,8 @@ class BIM_PT_resource_qtos(Panel):
if not ResourceQtosData.is_loaded: if not ResourceQtosData.is_loaded:
ResourceQtosData.load() ResourceQtosData.load()
props = context.scene.ResourcePsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "Resource")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(props, "qto_name", text="") row.prop(props, "qto_name", text="")
op = row.operator("bim.add_qto", icon="ADD", text="") op = row.operator("bim.add_qto", icon="ADD", text="")
@@ -638,7 +641,8 @@ class BIM_PT_resource_psets(Panel):
if not ResourcePsetsData.is_loaded: if not ResourcePsetsData.is_loaded:
ResourcePsetsData.load() ResourcePsetsData.load()
props = context.scene.ResourcePsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "Resource")
row = self.layout.row(align=True) row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
@@ -672,7 +676,8 @@ class BIM_PT_group_qtos(Panel):
if not GroupQtosData.is_loaded: if not GroupQtosData.is_loaded:
GroupQtosData.load() GroupQtosData.load()
props = context.scene.GroupPsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "Group")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(props, "qto_name", text="") row.prop(props, "qto_name", text="")
op = row.operator("bim.add_qto", icon="ADD", text="") op = row.operator("bim.add_qto", icon="ADD", text="")
@@ -706,7 +711,8 @@ class BIM_PT_group_psets(Panel):
if not GroupPsetData.is_loaded: if not GroupPsetData.is_loaded:
GroupPsetData.load() GroupPsetData.load()
props = context.scene.GroupPsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "Group")
row = self.layout.row(align=True) row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
@@ -750,7 +756,8 @@ class BIM_PT_profile_psets(Panel):
): ):
ProfilePsetsData.load() ProfilePsetsData.load()
props = context.scene.ProfilePsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "Profile")
row = self.layout.row(align=True) row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
@@ -782,7 +789,8 @@ class BIM_PT_work_schedule_psets(Panel):
if not WorkSchedulePsetsData.is_loaded: if not WorkSchedulePsetsData.is_loaded:
WorkSchedulePsetsData.load() WorkSchedulePsetsData.load()
props = context.scene.WorkSchedulePsetProperties assert self.layout
props = tool.Pset.get_pset_props("", "WorkSchedule")
row = self.layout.row(align=True) row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
+1 -1
View File
@@ -33,7 +33,7 @@ from bpy.props import (
FloatVectorProperty, FloatVectorProperty,
CollectionProperty, CollectionProperty,
) )
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Literal
def get_element_key(self: "BIMSearchProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]: def get_element_key(self: "BIMSearchProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
-1
View File
@@ -543,7 +543,6 @@ class Material:
def ensure_material_assigned(cls, elements, material_type, material): pass def ensure_material_assigned(cls, elements, material_type, material): pass
def ensure_material_unassigned(cls, elements): pass def ensure_material_unassigned(cls, elements): pass
def ensure_new_material_set_is_valid(cls, material): pass def ensure_new_material_set_is_valid(cls, material): pass
def get_active_material_item(cls): pass
def get_active_material_type(cls): pass def get_active_material_type(cls): pass
def get_default_material(cls): pass def get_default_material(cls): pass
def get_elements_by_material(cls, material): pass def get_elements_by_material(cls, material): pass
+3
View File
@@ -19,6 +19,7 @@
from __future__ import annotations from __future__ import annotations
import os import os
import json import json
import bmesh
import bpy import bpy
import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.api.material import ifcopenshell.api.material
@@ -70,6 +71,7 @@ class Debug(bonsai.core.tool.Debug):
mesh = bpy.data.meshes.new("Debug") mesh = bpy.data.meshes.new("Debug")
bm.to_mesh(mesh) bm.to_mesh(mesh)
obj = bpy.data.objects.new(name, mesh) obj = bpy.data.objects.new(name, mesh)
assert bpy.context.scene
bpy.context.scene.collection.objects.link(obj) bpy.context.scene.collection.objects.link(obj)
return obj return obj
@@ -80,6 +82,7 @@ class Debug(bonsai.core.tool.Debug):
mesh = bpy.data.meshes.new("Debug") mesh = bpy.data.meshes.new("Debug")
mesh.from_pydata(verts, edges, []) mesh.from_pydata(verts, edges, [])
obj = bpy.data.objects.new(name, mesh) obj = bpy.data.objects.new(name, mesh)
assert bpy.context.scene
bpy.context.scene.collection.objects.link(obj) bpy.context.scene.collection.objects.link(obj)
return obj return obj
+1 -9
View File
@@ -76,14 +76,6 @@ class Material(bonsai.core.tool.Material):
def get_elements_by_material(cls, material: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: def get_elements_by_material(cls, material: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
return ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material) return ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material)
@classmethod
def get_active_material_item(cls) -> Union[MaterialItem, None]:
"""Get active material props item if index is valid, otherwise, return None."""
props = tool.Material.get_material_props()
if 0 <= props.active_material_index < len(props.materials):
return props.materials[props.active_material_index]
return None
@classmethod @classmethod
def get_material_category(cls, material: ifcopenshell.entity_instance) -> str: def get_material_category(cls, material: ifcopenshell.entity_instance) -> str:
# IfcMaterial has Category since IFC4. # IfcMaterial has Category since IFC4.
@@ -95,7 +87,7 @@ class Material(bonsai.core.tool.Material):
# Store active category name to reselect it later. # Store active category name to reselect it later.
# Occurs when we expand/contract all categories. # Occurs when we expand/contract all categories.
active_item = cls.get_active_material_item() active_item = props.active_material
previously_selected_category = None previously_selected_category = None
if active_item and active_item.is_category: if active_item and active_item.is_category:
previously_selected_category = active_item.name previously_selected_category = active_item.name
+2 -2
View File
@@ -75,11 +75,11 @@ class Pset(bonsai.core.tool.Pset):
@classmethod @classmethod
def get_pset_props(cls, obj: str, obj_type: tool.Ifc.OBJECT_TYPE) -> PsetProperties: def get_pset_props(cls, obj: str, obj_type: tool.Ifc.OBJECT_TYPE) -> PsetProperties:
if obj_type == "Object": if obj_type == "Object":
return bpy.data.objects.get(obj).PsetProperties return bpy.data.objects[obj].PsetProperties
elif obj_type == "Material": elif obj_type == "Material":
return bpy.context.scene.MaterialPsetProperties return bpy.context.scene.MaterialPsetProperties
elif obj_type == "MaterialSetItem": elif obj_type == "MaterialSetItem":
return bpy.data.objects.get(obj).MaterialSetItemPsetProperties return bpy.data.objects[obj].MaterialSetItemPsetProperties
elif obj_type == "Task": elif obj_type == "Task":
return bpy.context.scene.TaskPsetProperties return bpy.context.scene.TaskPsetProperties
elif obj_type == "Resource": elif obj_type == "Resource":
+6 -2
View File
@@ -33,9 +33,10 @@ import ifcopenshell.util.date as ifcdateutils
import ifcopenshell.util.cost import ifcopenshell.util.cost
import ifcopenshell.util.resource import ifcopenshell.util.resource
import ifcopenshell.util.constraint import ifcopenshell.util.constraint
from typing import Any, Union, TYPE_CHECKING from typing import Any, Union, TYPE_CHECKING, Literal
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.prop import Attribute
from bonsai.bim.module.resource.prop import BIMResourceProperties from bonsai.bim.module.resource.prop import BIMResourceProperties
@@ -142,7 +143,9 @@ class Resource(bonsai.core.tool.Resource):
@classmethod @classmethod
def get_resource_time_attributes(cls) -> dict[str, Any]: def get_resource_time_attributes(cls) -> dict[str, Any]:
def callback(attributes, prop): import bonsai.bim.module.sequence.helper as helper
def callback(attributes: dict[str, Any], prop: Attribute) -> bool:
if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime": if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime":
if prop.is_null: if prop.is_null:
attributes[prop.name] = None attributes[prop.name] = None
@@ -155,6 +158,7 @@ class Resource(bonsai.core.tool.Resource):
return True return True
attributes[prop.name] = helper.parse_duration(prop.string_value) attributes[prop.name] = helper.parse_duration(prop.string_value)
return True return True
return False
props = bpy.context.scene.BIMResourceProperties props = bpy.context.scene.BIMResourceProperties
return bonsai.bim.helper.export_attributes(props.resource_time_attributes, callback) return bonsai.bim.helper.export_attributes(props.resource_time_attributes, callback)
+2 -2
View File
@@ -561,8 +561,8 @@ class Spatial(bonsai.core.tool.Spatial):
@classmethod @classmethod
def get_active_container(cls) -> Union[ifcopenshell.entity_instance, None]: def get_active_container(cls) -> Union[ifcopenshell.entity_instance, None]:
props = cls.get_spatial_props() props = cls.get_spatial_props()
if props.active_container_index < len(props.containers): if active_container := props.active_container:
container = tool.Ifc.get().by_id(props.containers[props.active_container_index].ifc_definition_id) container = tool.Ifc.get().by_id(active_container.ifc_definition_id)
return container return container
@classmethod @classmethod
@@ -17,6 +17,7 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>. # along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell import ifcopenshell
import ifcopenshell.api.alignment
from ifcopenshell import entity_instance from ifcopenshell import entity_instance
import math import math
@@ -5,6 +5,8 @@ defaults = {"Girth": 1.0, "WallThickness": 0.11}
depths = [2.0, 3.0] depths = [2.0, 3.0]
widths = [0.2, 0.3] widths = [0.2, 0.3]
Girth, Depth, WallThickness, Width = 0.0, 0.0, 0.0, 0.0
for d, w in itertools.product(depths, widths): for d, w in itertools.product(depths, widths):
D = dict(defaults, Depth=d, Width=w) D = dict(defaults, Depth=d, Width=w)
@@ -17,17 +17,21 @@
# along with IfcPatch. If not, see <http://www.gnu.org/licenses/>. # along with IfcPatch. If not, see <http://www.gnu.org/licenses/>.
import os import logging
import math import math
import os
from typing import Union
import ifcpatch
import ifcopenshell import ifcopenshell
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.util.unit
import ifcopenshell.util.schema
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.schema
import ifcopenshell.util.unit
class Patcher: class Patcher(ifcpatch.BasePatcher):
def __init__(self, file, logger): def __init__(self, file: ifcopenshell.file, logger: Union[logging.Logger, None] = None):
"""Fix missing door swings in Revit when viewing ArchiCAD IFCs """Fix missing door swings in Revit when viewing ArchiCAD IFCs
ArchiCAD has the ability to store 2D data with objects like doors for ArchiCAD has the ability to store 2D data with objects like doors for
@@ -56,10 +60,9 @@ class Patcher:
ifcpatch.execute({"input": "input.ifc", "file": model, "recipe": "FixArchiCADToRevitDoorSwings", "arguments": []}) ifcpatch.execute({"input": "input.ifc", "file": model, "recipe": "FixArchiCADToRevitDoorSwings", "arguments": []})
""" """
self.file = file super().__init__(file, logger)
self.logger = logger
def patch(self): def patch(self) -> None:
# Revit has the ability to switch between 3D representations and 2D # Revit has the ability to switch between 3D representations and 2D
# representations (e.g. in plan view). It does this by detecting IFC # representations (e.g. in plan view). It does this by detecting IFC
# representations that belong to either the Model Body representation # representations that belong to either the Model Body representation