mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
typing
This commit is contained in:
@@ -117,7 +117,7 @@ def update_bim_tool_props():
|
||||
if not representation:
|
||||
return
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
if element.is_a("IfcElementType") or element.is_a("IfcElement"):
|
||||
element_type = ifcopenshell.util.element.get_type(element)
|
||||
if element_type:
|
||||
@@ -130,7 +130,7 @@ def update_bim_tool_props():
|
||||
if not extrusion:
|
||||
return
|
||||
|
||||
def get_x_angle(extrusion):
|
||||
def get_x_angle(extrusion: ifcopenshell.entity_instance) -> float:
|
||||
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
|
||||
x_angle = Vector((0, 1)).angle_signed(Vector((y, z)))
|
||||
return x_angle
|
||||
@@ -332,7 +332,7 @@ def load_post(scene):
|
||||
georeference_props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
aggregate_props = bpy.context.scene.BIMAggregateProperties
|
||||
nest_props = bpy.context.scene.BIMNestProperties
|
||||
model_props = bpy.context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
if georeference_props.should_visualise:
|
||||
GeoreferenceDecorator.install(bpy.context)
|
||||
if aggregate_props.aggregate_decorator:
|
||||
|
||||
@@ -660,6 +660,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj.select_set(True)
|
||||
|
||||
def auto_generate_boundaries(self, space, space_obj):
|
||||
props = tool.Model.get_model_props()
|
||||
# Identify all potential building elements
|
||||
# TODO: don't select everything, use AABB culling in Blender
|
||||
building_elements = (
|
||||
@@ -775,9 +776,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
# we cheat by using the exterior boundary to mean "gross".
|
||||
exterior_boundary_polygon = shapely.Polygon(gross_boundary_polygon.exterior.coords)
|
||||
|
||||
parent_boundary = tool.Ifc.run(
|
||||
"root.create_entity", ifc_class=bpy.context.scene.BIMModelProperties.boundary_class
|
||||
)
|
||||
parent_boundary = tool.Ifc.run("root.create_entity", ifc_class=props.boundary_class)
|
||||
if building_element.is_a("IfcVirtualElement"):
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "VIRTUAL"
|
||||
else:
|
||||
@@ -854,9 +853,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if opening_polygon.intersection(exterior_boundary_polygon).area == 0:
|
||||
continue
|
||||
|
||||
boundary = tool.Ifc.run(
|
||||
"root.create_entity", ifc_class=bpy.context.scene.BIMModelProperties.boundary_class
|
||||
)
|
||||
boundary = tool.Ifc.run("root.create_entity", ifc_class=props.boundary_class)
|
||||
boundary.RelatingSpace = space
|
||||
boundary.RelatedBuildingElement = filling or opening
|
||||
boundary.ConnectionGeometry = self.create_connection_geometry_from_polygon(
|
||||
@@ -877,6 +874,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if not relating_space or not related_building_element:
|
||||
return
|
||||
|
||||
props = tool.Model.get_model_props()
|
||||
# Find which face on space should be bounded to related building element
|
||||
# TODO: Handle round wall where multiple faces need to be bound to the same related building element
|
||||
bm = bmesh.new()
|
||||
@@ -924,7 +922,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
):
|
||||
return
|
||||
|
||||
parent_boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
parent_boundary = tool.Ifc.run("root.create_entity", ifc_class=props.boundary_class)
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
# Set to EXTERNAL by default and turn later to internal if there is a corresponding boundary relating to an
|
||||
# internal space
|
||||
@@ -959,7 +957,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
continue
|
||||
|
||||
connection_geometry = self.create_connection_geometry_from_polygon(opening_polygon, target_face_matrix)
|
||||
boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
boundary = tool.Ifc.run("root.create_entity", ifc_class=props.boundary_class)
|
||||
boundary.RelatingSpace = relating_space
|
||||
boundary.RelatedBuildingElement = filling
|
||||
boundary.ConnectionGeometry = connection_geometry
|
||||
|
||||
@@ -54,7 +54,7 @@ class CoveringToolUI:
|
||||
@classmethod
|
||||
def draw(cls, context, layout, ifc_element_type=None):
|
||||
cls.layout = layout
|
||||
cls.props = context.scene.BIMModelProperties
|
||||
cls.props = tool.Model.get_model_props()
|
||||
cls.covering_props = context.scene.BIMCoveringProperties
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
|
||||
@@ -37,7 +37,7 @@ class Annotator:
|
||||
if related_element is None:
|
||||
location, _, _, _ = Annotator.get_placeholder_coords(bpy.context)
|
||||
else:
|
||||
obj.data.BIMAssignedProductProperties.related_element = related_element
|
||||
curve.BIMAssignedProductProperties.related_element = related_element
|
||||
location = related_element.location
|
||||
obj.location = location
|
||||
obj.hide_render = True
|
||||
@@ -47,8 +47,9 @@ class Annotator:
|
||||
tool.Blender.get_data_dir_path(Path("fonts") / "OpenGost Type B TT.ttf").__str__()
|
||||
)
|
||||
font.name = "OpenGost Type B TT"
|
||||
obj.data.font = font
|
||||
obj.data.BIMTextProperties.font_size = "2.5"
|
||||
curve.font = font
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.font_size = "2.5"
|
||||
collection = bpy.context.scene.camera.BIMObjectProperties.collection
|
||||
collection.objects.link(obj)
|
||||
Annotator.resize_text(obj)
|
||||
@@ -66,7 +67,8 @@ class Annotator:
|
||||
return
|
||||
# This is a magic number for OpenGost
|
||||
font_size = 1.6 / 1000
|
||||
font_size *= float(text_obj.data.BIMTextProperties.font_size)
|
||||
props = tool.Drawing.get_text_props(text_obj)
|
||||
font_size *= float(props.font_size)
|
||||
|
||||
font_size /= tool.Drawing.get_scale_ratio(tool.Drawing.get_diagram_scale(camera)["Scale"])
|
||||
|
||||
|
||||
@@ -303,7 +303,7 @@ class DecoratorData:
|
||||
if not element or not tool.Drawing.is_annotation_object_type(element, ["TEXT", "TEXT_LEADER"]):
|
||||
return None
|
||||
|
||||
props = obj.BIMTextProperties
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
# getting font size
|
||||
pset_data = ifcopenshell.util.element.get_pset(element, "EPset_Annotation") or {}
|
||||
# use `regular` as default
|
||||
@@ -399,7 +399,7 @@ class AnnotationData:
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.is_loaded = True
|
||||
cls.props = bpy.context.scene.BIMAnnotationProperties
|
||||
cls.props = tool.Drawing.get_annotation_props()
|
||||
cls.data["relating_type_id"] = cls.relating_type_id()
|
||||
cls.data["relating_types"] = cls.relating_types()
|
||||
|
||||
|
||||
@@ -589,7 +589,7 @@ class BaseDecorator:
|
||||
text_dir = self.get_annotation_direction(context, obj)
|
||||
|
||||
pos = location_3d_to_region_2d(region, region3d, text_world_position)
|
||||
props = obj.BIMTextProperties
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
text_data = DecoratorData.get_ifc_text_data(obj)
|
||||
if props.is_editing:
|
||||
text_data = text_data | props.get_text_edited_data()
|
||||
|
||||
@@ -416,7 +416,7 @@ def elevate_segment(bounds, segm):
|
||||
return [Vector((x, ymin, zmin)), Vector((x, ymax, zmin))]
|
||||
|
||||
|
||||
def add_newline_between_words(text, newline_at):
|
||||
def add_newline_between_words(text: str, newline_at: int) -> str:
|
||||
result = []
|
||||
start = 0
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class AddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMAnnotationProperties
|
||||
props = tool.Drawing.get_annotation_props()
|
||||
object_type = props.object_type
|
||||
has_representation = props.create_representation_for_type
|
||||
drawing = tool.Ifc.get_entity(bpy.context.scene.camera)
|
||||
@@ -115,7 +115,7 @@ class EnableAddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
bpy.context.scene.BIMAnnotationProperties.is_adding_type = True
|
||||
tool.Drawing.get_annotation_props().is_adding_type = True
|
||||
|
||||
|
||||
class DisableAddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -124,7 +124,7 @@ class DisableAddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
bpy.context.scene.BIMAnnotationProperties.is_adding_type = False
|
||||
tool.Drawing.get_annotation_props().is_adding_type = False
|
||||
|
||||
|
||||
class AddDrawing(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -1433,7 +1433,7 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return operator.description or ""
|
||||
|
||||
def _execute(self, context):
|
||||
props = bpy.context.scene.BIMAnnotationProperties
|
||||
props = tool.Drawing.get_annotation_props()
|
||||
if not (drawing := tool.Ifc.get_entity(context.scene.camera)):
|
||||
self.report({"WARNING"}, "Not a BIM camera")
|
||||
return
|
||||
@@ -2725,7 +2725,9 @@ class EditTextPopup(bpy.types.Operator):
|
||||
# need to keep them in sync or move to some common function
|
||||
# NOTE: that `popup_active_attribute` is used here when it's not used in `BIM_PT_text.draw()`
|
||||
|
||||
props = context.active_object.BIMTextProperties
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.add_text_literal", icon="ADD", text="Add Literal")
|
||||
@@ -2826,9 +2828,11 @@ class AddTextLiteral(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
|
||||
# similar to `tool.Drawing.import_text_attributes`
|
||||
literal_props = obj.BIMTextProperties.literals.add()
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
literal_props = props.literals.add()
|
||||
literal_attributes = literal_props.attributes
|
||||
literal_attr_values = {
|
||||
"Literal": "Literal",
|
||||
@@ -2865,7 +2869,9 @@ class RemoveTextLiteral(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
obj.BIMTextProperties.literals.remove(self.literal_prop_id)
|
||||
assert obj
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.literals.remove(self.literal_prop_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -2880,7 +2886,9 @@ class OrderTextLiteralUp(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
obj.BIMTextProperties.literals.move(self.literal_prop_id, self.literal_prop_id - 1)
|
||||
assert obj
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.literals.move(self.literal_prop_id, self.literal_prop_id - 1)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -2895,7 +2903,9 @@ class OrderTextLiteralDown(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
obj.BIMTextProperties.literals.move(self.literal_prop_id, self.literal_prop_id + 1)
|
||||
assert obj
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.literals.move(self.literal_prop_id, self.literal_prop_id + 1)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ from bpy.props import (
|
||||
CollectionProperty,
|
||||
BoolVectorProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Literal
|
||||
from typing import TYPE_CHECKING, Literal, Any
|
||||
|
||||
|
||||
diagram_scales_enum = []
|
||||
@@ -613,7 +613,13 @@ class BIMTextProperties(PropertyGroup):
|
||||
)
|
||||
newline_at: IntProperty(name="Newline At")
|
||||
|
||||
def get_text_edited_data(self):
|
||||
if TYPE_CHECKING:
|
||||
is_editing: bool
|
||||
literals: bpy.types.bpy_prop_collection_idprop[LiteralProps]
|
||||
font_size: str
|
||||
newline_at: int
|
||||
|
||||
def get_text_edited_data(self) -> dict[str, Any]:
|
||||
"""should be called only if `is_editing`
|
||||
otherwise should use `DecoratorData.get_ifc_text_data(obj)` instead
|
||||
because this data could be out of date
|
||||
@@ -676,3 +682,10 @@ class BIMAnnotationProperties(PropertyGroup):
|
||||
)
|
||||
is_adding_type: bpy.props.BoolProperty(default=False)
|
||||
type_name: bpy.props.StringProperty(name="Name", default="TYPEX")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
object_type: str
|
||||
relating_type_id: str
|
||||
create_representation_for_type: bool
|
||||
is_adding_type: bool
|
||||
type_name: str
|
||||
|
||||
@@ -520,7 +520,8 @@ class BIM_PT_text(Panel):
|
||||
|
||||
def draw(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMTextProperties
|
||||
assert obj
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
|
||||
if props.is_editing:
|
||||
# shares most of the code with EditTextPopup.draw()
|
||||
|
||||
@@ -45,7 +45,7 @@ class LaunchAnnotationTypeManager(bpy.types.Operator):
|
||||
if not AnnotationData.is_loaded:
|
||||
AnnotationData.load()
|
||||
|
||||
props = context.scene.BIMAnnotationProperties
|
||||
props = tool.Drawing.get_annotation_props()
|
||||
|
||||
columns = self.layout.column_flow(columns=3)
|
||||
row = columns.row()
|
||||
@@ -155,7 +155,7 @@ def add_layout_hotkey_operator(
|
||||
|
||||
# TODO: move to operator
|
||||
def create_annotation_occurrence(context):
|
||||
props = context.scene.BIMAnnotationProperties
|
||||
props = tool.Drawing.get_annotation_props()
|
||||
relating_type = tool.Ifc.get().by_id(int(props.relating_type_id))
|
||||
object_type = props.object_type
|
||||
|
||||
@@ -200,7 +200,7 @@ class AnnotationToolUI:
|
||||
@classmethod
|
||||
def draw(cls, context, layout):
|
||||
cls.layout = layout
|
||||
cls.props = context.scene.BIMAnnotationProperties
|
||||
cls.props = tool.Drawing.get_annotation_props()
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
if not tool.Ifc.get():
|
||||
@@ -279,19 +279,19 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
self.report({"ERROR"}, "No drawing active for annotation hotkeys.")
|
||||
return {"CANCELLED"}
|
||||
|
||||
self.props = context.scene.BIMAnnotationProperties
|
||||
self.props = tool.Drawing.get_annotation_props()
|
||||
getattr(self, f"hotkey_{self.hotkey}")()
|
||||
|
||||
def invoke(self, context, event):
|
||||
# https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey
|
||||
self.props = context.scene.BIMAnnotationProperties
|
||||
self.props = tool.Drawing.get_annotation_props()
|
||||
return self.execute(context)
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
|
||||
def hotkey_S_T(self):
|
||||
props = bpy.context.scene.BIMAnnotationProperties
|
||||
props = tool.Drawing.get_annotation_props()
|
||||
object_type = props.object_type
|
||||
|
||||
if object_type not in tool.Drawing.ANNOTATION_TYPES_SUPPORT_SETUP:
|
||||
|
||||
@@ -743,7 +743,7 @@ class OverrideDelete(bpy.types.Operator):
|
||||
else:
|
||||
bpy.data.objects.remove(obj)
|
||||
|
||||
for opening in context.scene.BIMModelProperties.openings:
|
||||
for opening in tool.Model.get_model_props().openings:
|
||||
if opening.obj is not None and not tool.Ifc.get_entity(opening.obj):
|
||||
bpy.data.objects.remove(opening.obj)
|
||||
tool.Model.purge_scene_openings()
|
||||
@@ -1874,7 +1874,7 @@ class OverrideEscape(bpy.types.Operator):
|
||||
elif context.scene.BIMGeometryProperties.mode == "EDIT":
|
||||
bpy.ops.bim.override_mode_set_object("INVOKE_DEFAULT", should_save=False)
|
||||
tool.Geometry.disable_item_mode()
|
||||
elif context.scene.BIMModelProperties.openings:
|
||||
elif tool.Model.get_model_props().openings:
|
||||
bpy.ops.bim.hide_all_openings()
|
||||
elif context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
bpy.ops.bim.disable_aggregate_mode()
|
||||
|
||||
@@ -51,7 +51,7 @@ class AuthoringData:
|
||||
@classmethod
|
||||
def load(cls, ifc_element_type=None):
|
||||
cls.is_loaded = True
|
||||
cls.props = bpy.context.scene.BIMModelProperties
|
||||
cls.props = tool.Model.get_model_props()
|
||||
if ifc_element_type:
|
||||
cls.ifc_element_type = None if ifc_element_type == "all" else ifc_element_type
|
||||
cls.data["default_container"] = cls.default_container()
|
||||
@@ -535,7 +535,9 @@ class DoorData:
|
||||
|
||||
@classmethod
|
||||
def general_params(cls):
|
||||
props = bpy.context.active_object.BIMDoorProperties
|
||||
obj = bpy.context.active_object
|
||||
assert obj
|
||||
props = tool.Model.get_door_props(obj)
|
||||
data = cls.data["pset_data"]["data_dict"]
|
||||
general_params = {}
|
||||
general_props = props.get_general_kwargs()
|
||||
@@ -546,7 +548,9 @@ class DoorData:
|
||||
|
||||
@classmethod
|
||||
def lining_params(cls):
|
||||
props = bpy.context.active_object.BIMDoorProperties
|
||||
obj = bpy.context.active_object
|
||||
assert obj
|
||||
props = tool.Model.get_door_props(obj)
|
||||
data = cls.data["pset_data"]["data_dict"]
|
||||
lining_data = data["lining_properties"]
|
||||
lining_params = {}
|
||||
@@ -558,7 +562,9 @@ class DoorData:
|
||||
|
||||
@classmethod
|
||||
def panel_params(cls):
|
||||
props = bpy.context.active_object.BIMDoorProperties
|
||||
obj = bpy.context.active_object
|
||||
assert obj
|
||||
props = tool.Model.get_door_props(obj)
|
||||
data = cls.data["pset_data"]["data_dict"]
|
||||
panel_data = cls.data["pset_data"]["data_dict"]["panel_properties"]
|
||||
panel_params = {}
|
||||
|
||||
@@ -829,7 +829,7 @@ class ProductDecorator:
|
||||
polyline_points = polyline_data[0].polyline_points if polyline_data else []
|
||||
|
||||
self.relating_type = None
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
|
||||
@@ -41,7 +41,7 @@ V_ = tool.Blender.V_
|
||||
|
||||
|
||||
def update_door_modifier_representation(obj: bpy.types.Object) -> None:
|
||||
props = obj.BIMDoorProperties
|
||||
props = tool.Model.get_door_props(obj)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
ifc_file = tool.Ifc.get()
|
||||
sliding_door = "SLIDING" in props.door_type
|
||||
@@ -338,7 +338,8 @@ def create_bm_door_lining(
|
||||
|
||||
def update_door_modifier_bmesh(context: bpy.types.Context) -> None:
|
||||
obj = context.active_object
|
||||
props = obj.BIMDoorProperties
|
||||
assert obj
|
||||
props = tool.Model.get_door_props(obj)
|
||||
|
||||
overall_width = props.overall_width
|
||||
overall_height = props.overall_height
|
||||
@@ -572,9 +573,10 @@ class AddDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_description = "Add a Parametric Door to the Selected IFC Door Elements"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def add_door_on_object(self, obj):
|
||||
def add_door_on_object(self, obj: bpy.types.Object) -> None:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
props = obj.BIMDoorProperties
|
||||
assert element
|
||||
props = tool.Model.get_door_props(obj)
|
||||
|
||||
door_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||
lining_props = props.get_lining_kwargs(convert_to_project_units=True)
|
||||
@@ -608,11 +610,12 @@ class CancelEditingDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_label = "Cancel Editing Door on Selected Objects"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def cancel_editing_door_on_object(self, obj):
|
||||
def cancel_editing_door_on_object(self, obj: bpy.types.Object) -> None:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
if not tool.Blender.Modifier.is_door(element):
|
||||
return
|
||||
props = obj.BIMDoorProperties
|
||||
props = tool.Model.get_door_props(obj)
|
||||
data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Door", "Data"))
|
||||
data.update(data.pop("lining_properties"))
|
||||
data.update(data.pop("panel_properties"))
|
||||
@@ -646,9 +649,10 @@ class FinishEditingDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def finish_editing_door_on_object(self, obj):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
if not tool.Blender.Modifier.is_door(element):
|
||||
return
|
||||
props = obj.BIMDoorProperties
|
||||
props = tool.Model.get_door_props(obj)
|
||||
|
||||
door_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||
lining_props = props.get_lining_kwargs(convert_to_project_units=True)
|
||||
@@ -678,9 +682,10 @@ class EnableEditingDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def edit_door_on_obj(self, obj):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
if not tool.Blender.Modifier.is_door(element):
|
||||
return
|
||||
props = obj.BIMDoorProperties
|
||||
props = tool.Model.get_door_props(obj)
|
||||
data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Door", "Data"))
|
||||
data.update(data.pop("lining_properties"))
|
||||
data.update(data.pop("panel_properties"))
|
||||
@@ -702,9 +707,11 @@ class RemoveDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def remove_door_on_object(self, obj):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
if not tool.Blender.Modifier.is_door(element):
|
||||
return
|
||||
obj.BIMDoorProperties.is_editing = False
|
||||
props = tool.Model.get_door_props(obj)
|
||||
props.is_editing = False
|
||||
|
||||
pset = tool.Pset.get_element_pset(element, "BBIM_Door")
|
||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), product=element, pset=pset)
|
||||
|
||||
@@ -60,7 +60,7 @@ class FilledOpeningGenerator:
|
||||
:param target: Target opening position. If ommited, cursor position is used.
|
||||
:return: None if there was no errors, otherwise returns a string with error message.
|
||||
"""
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
opening_thickness_si = 0.0
|
||||
|
||||
filling = tool.Ifc.get_entity(filling_obj)
|
||||
@@ -531,7 +531,8 @@ class UpdateOpeningsFocus(Operator):
|
||||
return {"FINISHED"}
|
||||
openings = set()
|
||||
building_objects = set()
|
||||
for opening in context.scene.BIMModelProperties.openings:
|
||||
props = tool.Model.get_model_props()
|
||||
for opening in props.openings:
|
||||
if opening.obj:
|
||||
openings.add(opening.obj)
|
||||
opening_element = tool.Ifc.get_entity(opening.obj)
|
||||
@@ -545,7 +546,7 @@ class UpdateOpeningsFocus(Operator):
|
||||
obj.color[2],
|
||||
(
|
||||
1
|
||||
if not context.scene.BIMModelProperties.openings
|
||||
if not props.openings
|
||||
or not building_objects
|
||||
or obj in openings
|
||||
or obj in building_objects
|
||||
@@ -558,7 +559,8 @@ class UpdateOpeningsFocus(Operator):
|
||||
|
||||
def hide_openings(context: bpy.types.Context, objects: Sequence[bpy.types.Object]) -> None:
|
||||
objects_to_remove = set()
|
||||
for opening_prop in context.scene.BIMModelProperties.openings:
|
||||
props = tool.Model.get_model_props()
|
||||
for opening_prop in props.openings:
|
||||
opening_obj = opening_prop.obj
|
||||
if not opening_obj:
|
||||
continue
|
||||
@@ -623,7 +625,7 @@ class EditOpenings(Operator, tool.Ifc.Operator):
|
||||
def get_buildings_and_openings(
|
||||
self, context: bpy.types.Context
|
||||
) -> tuple[set[bpy.types.Object], set[ifcopenshell.entity_instance]]:
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
building_objs: set[bpy.types.Object] = set()
|
||||
opening_elements: set[ifcopenshell.entity_instance] = set()
|
||||
objects_to_remove = set()
|
||||
@@ -892,7 +894,8 @@ class DecorationsHandler:
|
||||
batch.draw(shader)
|
||||
|
||||
def __call__(self, context):
|
||||
if not context.scene.BIMModelProperties.openings:
|
||||
props = tool.Model.get_model_props()
|
||||
if not props.openings:
|
||||
return
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
selected_elements_color = self.addon_prefs.decorator_color_selected
|
||||
@@ -907,7 +910,7 @@ class DecorationsHandler:
|
||||
gpu.state.point_size_set(6)
|
||||
gpu.state.blend_set("ALPHA")
|
||||
|
||||
for opening in context.scene.BIMModelProperties.openings:
|
||||
for opening in props.openings:
|
||||
obj = opening.obj
|
||||
if context.scene.BIMGeometryProperties.representation_obj == obj:
|
||||
# We are editing the representation of the opening :
|
||||
|
||||
@@ -23,6 +23,7 @@ import math
|
||||
import bmesh
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.placement
|
||||
@@ -40,7 +41,7 @@ from mathutils import Vector, Matrix, Quaternion
|
||||
from bonsai.bim.module.model.opening import FilledOpeningGenerator
|
||||
from bonsai.bim.module.model.decorator import PolylineDecorator
|
||||
from bonsai.bim.module.geometry.decorator import ItemDecorator
|
||||
from typing import Optional, Union, Literal
|
||||
from typing import Optional, Union, Literal, Any
|
||||
from lark import Lark, Transformer
|
||||
|
||||
|
||||
@@ -63,7 +64,7 @@ def create_bmesh_from_vertices(vertices, is_closed=False):
|
||||
|
||||
def get_wall_preview_data(context, relating_type):
|
||||
# Get properties from object type
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
direction_sense = model_props.direction_sense
|
||||
direction = 1
|
||||
if direction_sense == "NEGATIVE":
|
||||
@@ -190,9 +191,8 @@ def get_wall_preview_data(context, relating_type):
|
||||
|
||||
|
||||
def get_slab_preview_data(context, relating_type):
|
||||
props = context.scene.BIMModelProperties
|
||||
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
x_angle = 0 if tool.Cad.is_x(model_props.x_angle, 0, tolerance=0.001) else model_props.x_angle
|
||||
direction_sense = model_props.direction_sense
|
||||
direction = 1
|
||||
if direction_sense == "NEGATIVE":
|
||||
@@ -254,14 +254,16 @@ def get_slab_preview_data(context, relating_type):
|
||||
return data
|
||||
|
||||
|
||||
def get_vertical_profile_preview_data(context, relating_type):
|
||||
def get_vertical_profile_preview_data(
|
||||
context: bpy.types.Context, relating_type: ifcopenshell.entity_instance
|
||||
) -> dict[str, Any]:
|
||||
material = ifcopenshell.util.element.get_material(relating_type)
|
||||
try:
|
||||
profile = material.MaterialProfiles[0].Profile
|
||||
except:
|
||||
return {}
|
||||
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
extrusion_depth = model_props.extrusion_depth
|
||||
cardinal_point = model_props.cardinal_point
|
||||
rot_mat = Quaternion()
|
||||
@@ -373,7 +375,7 @@ def get_horizontal_profile_preview_data(context, relating_type):
|
||||
except:
|
||||
return {}
|
||||
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
cardinal_point = model_props.cardinal_point
|
||||
|
||||
polyline_verts = []
|
||||
@@ -497,7 +499,7 @@ def get_horizontal_profile_preview_data(context, relating_type):
|
||||
|
||||
|
||||
def get_generic_product_preview_data(context, relating_type):
|
||||
model_props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
if relating_type.is_a("IfcDoorType"):
|
||||
rl = float(model_props.rl1)
|
||||
elif relating_type.is_a("IfcWindowType"):
|
||||
@@ -914,7 +916,7 @@ class PolylineOperator:
|
||||
t.value_3d = tri
|
||||
|
||||
def set_offset(self, context: bpy.types.Context, relating_type: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
direction_sense = props.direction_sense
|
||||
if tool.Model.get_usage_type(relating_type) == "LAYER2":
|
||||
offset_type = "offset_type_vertical"
|
||||
|
||||
@@ -200,7 +200,7 @@ class AddOccurrence(bpy.types.Operator, PolylineOperator):
|
||||
|
||||
def modal(self, context, event):
|
||||
# Ensure state of BIM tool props is valid
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = tool.Blender.get_enum_safe(props, "relating_type_id")
|
||||
relating_type_id_data = AuthoringData.data["relating_type_id"]
|
||||
if not relating_type_id and relating_type_id_data:
|
||||
@@ -284,7 +284,7 @@ class AddConstrTypeInstance(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
|
||||
def invoke(self, context, event):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = self.relating_type_id or props.relating_type_id
|
||||
if (
|
||||
relating_type_id
|
||||
@@ -303,7 +303,7 @@ class AddConstrTypeInstance(bpy.types.Operator, tool.Ifc.Operator):
|
||||
row.prop(self, "representation_template", text="")
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = self.relating_type_id or props.relating_type_id
|
||||
|
||||
if not relating_type_id:
|
||||
@@ -507,7 +507,8 @@ class AddConstrTypeInstance(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def set_flow_segment_rl(self, obj):
|
||||
if self.container_obj:
|
||||
obj.location[2] = self.container_obj.location[2] + bpy.context.scene.BIMModelProperties.rl2
|
||||
props = tool.Model.get_model_props()
|
||||
obj.location[2] = self.container_obj.location[2] + props.rl2
|
||||
|
||||
@staticmethod
|
||||
def generate_layered_element(ifc_class: str, relating_type: ifcopenshell.entity_instance) -> bool:
|
||||
@@ -535,7 +536,7 @@ class ChangeTypePage(bpy.types.Operator, tool.Ifc.Operator):
|
||||
page: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
bpy.ops.bim.load_type_thumbnails(ifc_class=props.ifc_class, offset=9 * (self.page - 1), limit=9)
|
||||
props.type_page = self.page
|
||||
return {"FINISHED"}
|
||||
@@ -548,7 +549,7 @@ class SetActiveType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
relating_type: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
props.relating_type_id = str(self.relating_type)
|
||||
|
||||
|
||||
@@ -623,7 +624,7 @@ class LoadTypeThumbnails(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if bpy.app.background:
|
||||
return
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
# Only process at most one paginated class at a time.
|
||||
# Large projects have hundreds of types which can lead to unnecessary lag.
|
||||
if not AuthoringData.is_loaded:
|
||||
|
||||
@@ -57,7 +57,7 @@ class DumbProfileGenerator:
|
||||
|
||||
self.body_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
|
||||
self.axis_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Axis", "GRAPH_VIEW")
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
|
||||
self.container = None
|
||||
self.container_obj = None
|
||||
@@ -68,7 +68,7 @@ class DumbProfileGenerator:
|
||||
self.depth = props.extrusion_depth
|
||||
self.rotation = 0
|
||||
self.location = Vector((0, 0, 0))
|
||||
self.cardinal_point = int(bpy.context.scene.BIMModelProperties.cardinal_point)
|
||||
self.cardinal_point = int(props.cardinal_point)
|
||||
if insertion_type == "POLYLINE":
|
||||
return self.derive_from_polyline()
|
||||
elif insertion_type == "CURSOR":
|
||||
@@ -1123,7 +1123,7 @@ class DrawPolylineProfile(bpy.types.Operator, PolylineOperator):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.relating_type = None
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
@@ -1132,7 +1132,7 @@ class DrawPolylineProfile(bpy.types.Operator, PolylineOperator):
|
||||
if not self.relating_type:
|
||||
return {"FINISHED"}
|
||||
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
direction_sense = model_props.direction_sense
|
||||
offset = model_props.offset
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ from bonsai.bim.module.model.data import AuthoringData
|
||||
from bpy.types import PropertyGroup, NodeTree
|
||||
from math import pi, radians
|
||||
from bonsai.bim.module.model.decorator import WallAxisDecorator, SlabDirectionDecorator
|
||||
from typing import TYPE_CHECKING, Literal, get_args
|
||||
|
||||
|
||||
def get_ifc_class(self, context):
|
||||
@@ -230,6 +231,39 @@ class BIMModelProperties(PropertyGroup):
|
||||
update=update_slab_direction_decorator,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ifc_class: str
|
||||
relating_type_id: str
|
||||
search_name: str
|
||||
menu_relating_type_id: int
|
||||
icon_id: int
|
||||
updating: bool
|
||||
occurrence_name_style: Literal["CLASS", "TYPE", "CUSTOM"]
|
||||
occurrence_name_function: str
|
||||
extrusion_depth: float
|
||||
cardinal_point: Literal[
|
||||
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"
|
||||
]
|
||||
length: float
|
||||
openings: bpy.types.bpy_prop_collection_idprop[ObjProperty]
|
||||
x: float
|
||||
y: float
|
||||
z: float
|
||||
rl_mode: Literal["BOTTOM", "CONTAINER", "CURSOR"]
|
||||
rl1: float
|
||||
rl2: float
|
||||
rl3: float
|
||||
type_page: int
|
||||
x_angle: float
|
||||
type_name: str
|
||||
boundary_class: str
|
||||
direction_sense: Literal["POSITIVE", "NEGATIVE"]
|
||||
offset_type_vertical: Literal["EXTERIOR", "CENTER", "INTERIOR"]
|
||||
offset_type_horizontal: Literal["TOP", "CENTER", "BOTTOM"]
|
||||
offset: float
|
||||
show_wall_axis: bool
|
||||
show_slab_direction: bool
|
||||
|
||||
|
||||
class BIMArrayProperties(PropertyGroup):
|
||||
is_editing: bpy.props.IntProperty(
|
||||
@@ -550,21 +584,24 @@ class BIMWindowProperties(PropertyGroup):
|
||||
setattr(self, prop_name, kwargs[prop_name])
|
||||
|
||||
|
||||
DoorType = Literal[
|
||||
"SINGLE_SWING_LEFT",
|
||||
"SINGLE_SWING_RIGHT",
|
||||
"DOUBLE_SWING_LEFT",
|
||||
"DOUBLE_SWING_RIGHT",
|
||||
"DOUBLE_DOOR_SINGLE_SWING",
|
||||
"SLIDING_TO_LEFT",
|
||||
"SLIDING_TO_RIGHT",
|
||||
"DOUBLE_DOOR_SLIDING",
|
||||
]
|
||||
|
||||
|
||||
class BIMDoorProperties(PropertyGroup):
|
||||
non_si_units_props = ("is_editing", "door_type", "panel_width_ratio")
|
||||
door_types = (
|
||||
("SINGLE_SWING_LEFT", "SINGLE_SWING_LEFT", ""),
|
||||
("SINGLE_SWING_RIGHT", "SINGLE_SWING_RIGHT", ""),
|
||||
("DOUBLE_SWING_LEFT", "DOUBLE_SWING_LEFT", ""),
|
||||
("DOUBLE_SWING_RIGHT", "DOUBLE_SWING_RIGHT", ""),
|
||||
("DOUBLE_DOOR_SINGLE_SWING", "DOUBLE_DOOR_SINGLE_SWING", ""),
|
||||
("SLIDING_TO_LEFT", "SLIDING_TO_LEFT", ""),
|
||||
("SLIDING_TO_RIGHT", "SLIDING_TO_RIGHT", ""),
|
||||
("DOUBLE_DOOR_SLIDING", "DOUBLE_DOOR_SLIDING", ""),
|
||||
)
|
||||
|
||||
is_editing: bpy.props.BoolProperty(default=False)
|
||||
door_type: bpy.props.EnumProperty(name="Door Operation Type", items=door_types, default="SINGLE_SWING_LEFT")
|
||||
door_type: bpy.props.EnumProperty(
|
||||
name="Door Operation Type", items=tuple((i, i, "") for i in get_args(DoorType)), default="SINGLE_SWING_LEFT"
|
||||
)
|
||||
overall_height: bpy.props.FloatProperty(name="Overall Height", default=2.0, subtype="DISTANCE")
|
||||
overall_width: bpy.props.FloatProperty(name="Overall Width", default=0.9, subtype="DISTANCE")
|
||||
|
||||
@@ -631,6 +668,42 @@ class BIMDoorProperties(PropertyGroup):
|
||||
panel_material: bpy.props.EnumProperty(name="Panel Material", items=get_materials, options=set())
|
||||
lining_material: bpy.props.EnumProperty(name="Lining Material", items=get_materials, options=set())
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_editing: bool
|
||||
door_type: DoorType
|
||||
overall_height: float
|
||||
overall_width: float
|
||||
|
||||
# Lining.
|
||||
lining_depth: float
|
||||
lining_thickness: float
|
||||
lining_offset: float
|
||||
lining_to_panel_offset_x: float
|
||||
lining_to_panel_offset_y: float
|
||||
|
||||
# Transom.
|
||||
transom_thickness: float
|
||||
transom_offset: float
|
||||
|
||||
# Casing.
|
||||
casing_thickness: float
|
||||
casing_depth: float
|
||||
|
||||
# Threshold.
|
||||
threshold_thickness: float
|
||||
threshold_depth: float
|
||||
threshold_offset: float
|
||||
|
||||
# Panel.
|
||||
panel_depth: float
|
||||
panel_width_ratio: float
|
||||
frame_thickness: float
|
||||
frame_depth: float
|
||||
|
||||
# Material.
|
||||
panel_material: str
|
||||
lining_material: str
|
||||
|
||||
def get_general_kwargs(self, convert_to_project_units=False):
|
||||
kwargs = {
|
||||
"door_type": self.door_type,
|
||||
|
||||
@@ -62,7 +62,7 @@ class DumbSlabGenerator:
|
||||
tool.Ifc.get(), "Plan", "FootPrint", "SKETCH_VIEW"
|
||||
)
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
|
||||
self.polyline = None
|
||||
self.container = None
|
||||
@@ -319,7 +319,7 @@ class DumbSlabPlaner:
|
||||
extrusion.Position.Location.Coordinates = tuple(rot_offset)
|
||||
|
||||
else:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
|
||||
new_rep = ifcopenshell.api.run(
|
||||
"geometry.add_slab_representation",
|
||||
@@ -344,7 +344,7 @@ class DumbSlabPlaner:
|
||||
)
|
||||
return
|
||||
else:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
|
||||
representation = ifcopenshell.api.run(
|
||||
"geometry.add_slab_representation",
|
||||
@@ -844,7 +844,7 @@ class AddSlabFromWall(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def __init__(self):
|
||||
self.relating_type = None
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
@@ -876,7 +876,7 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.relating_type = None
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
@@ -887,7 +887,7 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
|
||||
|
||||
slab = DumbSlabGenerator(self.relating_type).generate("POLYLINE")
|
||||
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
direction_sense = model_props.direction_sense
|
||||
offset = model_props.offset
|
||||
model = IfcStore.get_file()
|
||||
@@ -920,13 +920,11 @@ class DrawPolylineSlab(bpy.types.Operator, PolylineOperator):
|
||||
self.handle_mouse_move(context, event)
|
||||
return {"PASS_THROUGH"}
|
||||
|
||||
props = tool.Model.get_model_props()
|
||||
if event.value == "RELEASE" and event.type == "F":
|
||||
direction_sense = context.scene.BIMModelProperties.direction_sense
|
||||
context.scene.BIMModelProperties.direction_sense = (
|
||||
"NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE"
|
||||
)
|
||||
direction_sense = props.direction_sense
|
||||
props.direction_sense = "NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE"
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
if event.value == "RELEASE" and event.type == "O":
|
||||
items = ["TOP", "CENTER", "BOTTOM"]
|
||||
index = items.index(props.offset_type_horizontal)
|
||||
|
||||
@@ -55,7 +55,7 @@ class BIM_MT_type_menu(bpy.types.Menu):
|
||||
relating_type_id: bpy.props.IntProperty(name="Relating Type Id")
|
||||
|
||||
def draw(self, context):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
layout = self.layout
|
||||
op = layout.operator("bim.launch_rename_type", icon="GREASEPENCIL", text="Rename Type")
|
||||
op.element = props.menu_relating_type_id
|
||||
@@ -74,7 +74,7 @@ class LaunchTypeMenu(bpy.types.Operator):
|
||||
relating_type_id: bpy.props.IntProperty(name="Relating Type Id")
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
props.menu_relating_type_id = self.relating_type_id
|
||||
bpy.ops.wm.call_menu(name="BIM_MT_type_menu")
|
||||
return {"FINISHED"}
|
||||
@@ -90,7 +90,7 @@ class LaunchTypeManager(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
props.type_page = 1
|
||||
if get_ifc_class(None, context):
|
||||
ifc_class = AuthoringData.data["ifc_class_current"] or AuthoringData.data["ifc_element_type"]
|
||||
@@ -103,7 +103,7 @@ class LaunchTypeManager(bpy.types.Operator):
|
||||
return context.window_manager.invoke_props_dialog(self, width=550, title="Type Manager", confirm_text="Close")
|
||||
|
||||
def draw(self, context):
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
row = self.layout.row(align=True)
|
||||
text = f"{AuthoringData.data['total_types']} {AuthoringData.data['ifc_element_type'] or 'Types'}"
|
||||
if AuthoringData.data["total_types"] > 1:
|
||||
@@ -518,7 +518,9 @@ class BIM_PT_door(bpy.types.Panel):
|
||||
if not DoorData.is_loaded:
|
||||
DoorData.load()
|
||||
|
||||
props = context.active_object.BIMDoorProperties
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
props = tool.Model.get_door_props(obj)
|
||||
|
||||
if DoorData.data["pset_data"]:
|
||||
row = self.layout.row(align=True)
|
||||
|
||||
@@ -334,7 +334,7 @@ class AddWallsFromSlab(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def __init__(self):
|
||||
self.relating_type = None
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
@@ -368,7 +368,7 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.relating_type = None
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
if relating_type_id:
|
||||
self.relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
@@ -377,7 +377,7 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
||||
if not self.relating_type:
|
||||
return {"FINISHED"}
|
||||
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
direction_sense = model_props.direction_sense
|
||||
offset = model_props.offset
|
||||
|
||||
@@ -420,17 +420,15 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator):
|
||||
self.handle_mouse_move(context, event)
|
||||
return {"PASS_THROUGH"}
|
||||
|
||||
props = tool.Model.get_model_props()
|
||||
# Wall axis settings
|
||||
if event.value == "RELEASE" and event.type == "F":
|
||||
direction_sense = context.scene.BIMModelProperties.direction_sense
|
||||
context.scene.BIMModelProperties.direction_sense = (
|
||||
"NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE"
|
||||
)
|
||||
direction_sense = props.direction_sense
|
||||
props.direction_sense = "NEGATIVE" if direction_sense == "POSITIVE" else "POSITIVE"
|
||||
self.set_offset(context, self.relating_type)
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
if event.value == "RELEASE" and event.type == "O":
|
||||
items = ["EXTERIOR", "CENTER", "INTERIOR"]
|
||||
items = ("EXTERIOR", "CENTER", "INTERIOR")
|
||||
index = items.index(props.offset_type_vertical)
|
||||
size = len(items)
|
||||
props.offset_type_vertical = items[((index + 1) % size)]
|
||||
@@ -608,7 +606,7 @@ class DumbWallGenerator:
|
||||
self.body_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
|
||||
self.axis_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Plan", "Axis", "GRAPH_VIEW")
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
|
||||
self.container = None
|
||||
self.container_obj = None
|
||||
@@ -800,7 +798,7 @@ class DumbWallGenerator:
|
||||
return self.create_wall()
|
||||
|
||||
def create_wall(self) -> bpy.types.Object:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
ifc_class = self.get_relating_type_class(self.relating_type)
|
||||
mesh = bpy.data.meshes.new("Dummy")
|
||||
obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh)
|
||||
|
||||
@@ -21,6 +21,7 @@ import bpy
|
||||
import json
|
||||
import bmesh
|
||||
import collections
|
||||
import collections.abc
|
||||
import ifcopenshell
|
||||
import bonsai.tool as tool
|
||||
import bonsai.core.root
|
||||
@@ -33,7 +34,7 @@ import ifcopenshell.util.shape_builder
|
||||
import ifcopenshell.util.unit
|
||||
from bmesh.types import BMVert
|
||||
from mathutils import Vector
|
||||
from typing import Optional
|
||||
from typing import Optional, Union
|
||||
|
||||
V_ = tool.Blender.V_
|
||||
|
||||
@@ -132,7 +133,7 @@ def update_window_modifier_representation(context: bpy.types.Context) -> None:
|
||||
|
||||
|
||||
def create_bm_window_frame(
|
||||
bm: bmesh.types.BMesh, size: Vector, thickness: list, position: Vector = V_(0, 0, 0).freeze()
|
||||
bm: bmesh.types.BMesh, size: Vector, thickness: Union[float, list[float]], position: Vector = V_(0, 0, 0).freeze()
|
||||
) -> list[bmesh.types.BMVert]:
|
||||
"""`thickness` of the profile is defined as list in the following order:
|
||||
`(LEFT, TOP, RIGHT, BOTTOM)`
|
||||
|
||||
@@ -503,7 +503,7 @@ class CreateObjectUI:
|
||||
cls, context: bpy.types.Context, layout: bpy.types.UILayout, ifc_element_type: Optional[str] = None
|
||||
) -> None:
|
||||
cls.layout = layout
|
||||
cls.props = context.scene.BIMModelProperties
|
||||
cls.props = tool.Model.get_model_props()
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
if not tool.Ifc.get():
|
||||
@@ -733,7 +733,7 @@ class EditObjectUI:
|
||||
cls, context: bpy.types.Context, layout: bpy.types.UILayout, ifc_element_type: Optional[str] = None
|
||||
) -> None:
|
||||
cls.layout = layout
|
||||
cls.props = context.scene.BIMModelProperties
|
||||
cls.props = tool.Model.get_model_props()
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
row.separator()
|
||||
@@ -1099,7 +1099,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return operator.description or ""
|
||||
|
||||
def _execute(self, context):
|
||||
self.props = context.scene.BIMModelProperties
|
||||
self.props = tool.Model.get_model_props()
|
||||
self.has_ifc_class = True
|
||||
|
||||
self.active_class = None
|
||||
@@ -1118,7 +1118,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def invoke(self, context, event):
|
||||
# https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey
|
||||
self.props = context.scene.BIMModelProperties
|
||||
self.props = tool.Model.get_model_props()
|
||||
self.x = self.props.x
|
||||
self.y = self.props.y
|
||||
self.z = self.props.z
|
||||
@@ -1138,7 +1138,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.ops.wm.call_menu(name="BIM_MT_add_representation_item")
|
||||
return
|
||||
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_class = AuthoringData.data["ifc_class_current"]
|
||||
if not (relating_type_id := tool.Blender.get_enum_safe(props, "relating_type_id")):
|
||||
self.report({"ERROR"}, "No relating type selected")
|
||||
@@ -1431,7 +1431,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.ops.bim.enable_editing_extrusion_axis()
|
||||
|
||||
def hotkey_A_O(self):
|
||||
if bpy.context.scene.BIMModelProperties.openings:
|
||||
if tool.Model.get_model_props().openings:
|
||||
bpy.ops.bim.edit_openings(apply_all=True)
|
||||
else:
|
||||
bpy.ops.bim.show_openings()
|
||||
|
||||
@@ -579,7 +579,7 @@ class AddElement(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
if props.ifc_product == "IfcFeatureElement":
|
||||
tool.Feature.add_feature(props.featured_obj, [obj])
|
||||
new = context.scene.BIMModelProperties.openings.add()
|
||||
new = tool.Model.get_model_props().openings.add()
|
||||
new.obj = obj
|
||||
bpy.ops.bim.show_openings()
|
||||
tool.Model.purge_scene_openings()
|
||||
|
||||
@@ -58,7 +58,7 @@ class SpatialToolUI:
|
||||
@classmethod
|
||||
def draw(cls, context, layout):
|
||||
cls.layout = layout
|
||||
cls.model_props = context.scene.BIMModelProperties
|
||||
cls.model_props = tool.Model.get_model_props()
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
if not tool.Ifc.get():
|
||||
|
||||
@@ -48,7 +48,7 @@ class AssignType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if self.related_object
|
||||
else context.selected_objects or [context.active_object]
|
||||
)
|
||||
model_props = context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
for obj in related_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
core.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type)
|
||||
@@ -332,11 +332,11 @@ class DuplicateType(bpy.types.Operator, tool.Ifc.Operator):
|
||||
else:
|
||||
self.report({"INFO"}, "Type object can't be selected : It may be hidden or in an excluded collection.")
|
||||
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
|
||||
ifc_class = new.is_a()
|
||||
# Set duplicated type as active in current tool.
|
||||
if ifc_class in (i[0] for i in (bonsai.bim.helper.get_enum_items(props, "ifc_class", context) or ()) if i):
|
||||
context.scene.BIMModelProperties.ifc_class = new.is_a()
|
||||
context.scene.BIMModelProperties.relating_type_id = str(new_obj.BIMObjectProperties.ifc_definition_id)
|
||||
props.ifc_class = new.is_a()
|
||||
props.relating_type_id = str(new_obj.BIMObjectProperties.ifc_definition_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -347,10 +347,11 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||
layout.prop(context.scene.BIMProjectProperties, "should_disable_undo_on_save")
|
||||
layout.prop(context.scene.BIMProjectProperties, "should_stream")
|
||||
|
||||
def draw_model_settings(self, layout, context):
|
||||
layout.prop(context.scene.BIMModelProperties, "occurrence_name_style")
|
||||
if context.scene.BIMModelProperties == "CUSTOM":
|
||||
layout.prop(context.scene.BIMModelProperties, "occurrence_name_function")
|
||||
def draw_model_settings(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None:
|
||||
props = tool.Model.get_model_props()
|
||||
layout.prop(props, "occurrence_name_style")
|
||||
if props == "CUSTOM":
|
||||
layout.prop(props, "occurrence_name_function")
|
||||
|
||||
def draw_directories(self, layout, context):
|
||||
row = layout.row(align=True)
|
||||
@@ -1221,7 +1222,7 @@ class BIM_PT_decorators_overlay(Panel):
|
||||
georeference_props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
aggregate_props = bpy.context.scene.BIMAggregateProperties
|
||||
nest_props = bpy.context.scene.BIMNestProperties
|
||||
model_props = bpy.context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
display_all = overlay.show_overlays
|
||||
|
||||
col = layout.column()
|
||||
|
||||
@@ -1035,7 +1035,8 @@ class Blender(bonsai.core.tool.Blender):
|
||||
|
||||
@classmethod
|
||||
def is_editing_door_parameters(cls, obj: bpy.types.Object) -> bool:
|
||||
return obj.BIMDoorProperties.is_editing
|
||||
props = tool.Model.get_door_props(obj)
|
||||
return props.is_editing
|
||||
|
||||
@classmethod
|
||||
def is_editing_stair_parameters(cls, obj: bpy.types.Object) -> bool:
|
||||
|
||||
@@ -66,7 +66,7 @@ class Covering(bonsai.core.tool.Covering):
|
||||
) -> bool:
|
||||
if not tool.Ifc.get():
|
||||
return False
|
||||
props = context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = tool.Blender.get_enum_safe(props, "relating_type_id")
|
||||
if relating_type_id is not None:
|
||||
relating_type = ifcopenshell.util.element.get_predefined_type(tool.Ifc.get().by_id(int(relating_type_id)))
|
||||
|
||||
@@ -55,7 +55,7 @@ from typing import Optional, Union, Iterable, Any, Literal, Sequence, TYPE_CHECK
|
||||
from pathlib import Path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.drawing.prop import DocProperties, Sheet
|
||||
from bonsai.bim.module.drawing.prop import DocProperties, Sheet, BIMAnnotationProperties, BIMTextProperties
|
||||
from bonsai.bim.module.drawing.prop import Drawing as DrawingProperties
|
||||
|
||||
|
||||
@@ -91,6 +91,14 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
def get_document_props(cls) -> DocProperties:
|
||||
return bpy.context.scene.DocProperties
|
||||
|
||||
@classmethod
|
||||
def get_annotation_props(cls) -> BIMAnnotationProperties:
|
||||
return bpy.context.scene.BIMAnnotationProperties
|
||||
|
||||
@classmethod
|
||||
def get_text_props(cls, obj: bpy.types.Object) -> BIMTextProperties:
|
||||
return obj.BIMTextProperties
|
||||
|
||||
@classmethod
|
||||
def canonicalise_class_name(cls, name: str) -> str:
|
||||
return re.sub("[^0-9a-zA-Z]+", "", name)
|
||||
@@ -349,7 +357,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def disable_editing_text(cls, obj: bpy.types.Object) -> None:
|
||||
obj.BIMTextProperties.is_editing = False
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def disable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
|
||||
@@ -385,7 +394,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def enable_editing_text(cls, obj: bpy.types.Object) -> None:
|
||||
obj.BIMTextProperties.is_editing = True
|
||||
props = cls.get_text_props(obj)
|
||||
props.is_editing = True
|
||||
|
||||
@classmethod
|
||||
def enable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
|
||||
@@ -409,7 +419,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
@classmethod
|
||||
def export_text_literal_attributes(cls, obj: bpy.types.Object) -> list[dict[str, Any]]:
|
||||
literals = []
|
||||
for literal_props in obj.BIMTextProperties.literals:
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
for literal_props in props.literals:
|
||||
literal_data = bonsai.bim.helper.export_attributes(literal_props.attributes)
|
||||
literals.append(literal_data)
|
||||
return literals
|
||||
@@ -620,7 +631,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
def synchronise_ifc_and_text_attributes(cls, obj: bpy.types.Object) -> None:
|
||||
literals = cls.get_text_literal(obj, return_list=True)
|
||||
literals_attributes = cls.export_text_literal_attributes(obj)
|
||||
defined_ifc_ids = [l.ifc_definition_id for l in obj.BIMTextProperties.literals]
|
||||
props = cls.get_text_props(obj)
|
||||
defined_ifc_ids = [l.ifc_definition_id for l in props.literals]
|
||||
ifc_file = tool.Ifc.get()
|
||||
|
||||
for ifc_definition_id, attributes in zip(defined_ifc_ids, literals_attributes):
|
||||
@@ -921,7 +933,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
def import_text_attributes(cls, obj: bpy.types.Object) -> None:
|
||||
from bonsai.bim.module.drawing.prop import BOX_ALIGNMENT_POSITIONS
|
||||
|
||||
props = obj.BIMTextProperties
|
||||
props = cls.get_text_props(obj)
|
||||
props.literals.clear()
|
||||
|
||||
for ifc_literal in cls.get_text_literal(obj, return_list=True):
|
||||
@@ -1035,7 +1047,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def update_text_value(cls, obj: bpy.types.Object) -> None:
|
||||
props = obj.BIMTextProperties
|
||||
props = cls.get_text_props(obj)
|
||||
literals = cls.get_text_literal(obj, return_list=True)
|
||||
cls.import_text_attributes(obj)
|
||||
for i, literal in enumerate(literals):
|
||||
@@ -1049,7 +1061,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
"""
|
||||
from bonsai.bim.module.drawing.data import FONT_SIZES
|
||||
|
||||
props = obj.BIMTextProperties
|
||||
props = cls.get_text_props(obj)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
# updating text font size in EPset_Annotation.Classes
|
||||
font_size = float(props.font_size)
|
||||
@@ -1080,7 +1092,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def update_newline_at(cls, obj: bpy.types.Object) -> None:
|
||||
props = obj.BIMTextProperties
|
||||
props = cls.get_text_props(obj)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
newline_at = int(props.newline_at)
|
||||
ifc_file = tool.Ifc.get()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import json
|
||||
import bmesh
|
||||
@@ -47,13 +48,24 @@ from bonsai.bim.module.geometry.helper import Helper
|
||||
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData, WindowData, DoorData
|
||||
from bonsai.bim.module.model.opening import FilledOpeningGenerator
|
||||
from ifcopenshell.util.shape_builder import ShapeBuilder
|
||||
from typing import Optional, Union, TypeVar, Any, Iterable, Literal
|
||||
from typing import Optional, Union, TypeVar, Any, Iterable, Literal, TYPE_CHECKING
|
||||
|
||||
T = TypeVar("T")
|
||||
V_ = tool.Blender.V_
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.model.prop import BIMModelProperties, BIMDoorProperties
|
||||
|
||||
|
||||
class Model(bonsai.core.tool.Model):
|
||||
@classmethod
|
||||
def get_model_props(cls) -> BIMModelProperties:
|
||||
return bpy.context.scene.BIMModelProperties
|
||||
|
||||
@classmethod
|
||||
def get_door_props(cls, obj: bpy.types.Object) -> BIMDoorProperties:
|
||||
return obj.BIMDoorProperties
|
||||
|
||||
@classmethod
|
||||
def convert_si_to_unit(cls, value: T) -> T:
|
||||
if isinstance(value, (tuple, list)):
|
||||
@@ -215,7 +227,7 @@ class Model(bonsai.core.tool.Model):
|
||||
|
||||
@classmethod
|
||||
def generate_occurrence_name(cls, element_type: ifcopenshell.entity_instance, ifc_class: str) -> str:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = cls.get_model_props()
|
||||
if props.occurrence_name_style == "CLASS":
|
||||
return ifc_class[3:]
|
||||
elif props.occurrence_name_style == "TYPE":
|
||||
@@ -521,7 +533,8 @@ class Model(bonsai.core.tool.Model):
|
||||
@classmethod
|
||||
def purge_scene_openings(cls) -> None:
|
||||
"""Purge removed scene openings."""
|
||||
openings = bpy.context.scene.BIMModelProperties.openings
|
||||
props = cls.get_model_props()
|
||||
openings = props.openings
|
||||
for i in range(len(openings) - 1, -1, -1):
|
||||
if not openings[i].obj:
|
||||
openings.remove(i)
|
||||
@@ -1929,7 +1942,8 @@ class Model(bonsai.core.tool.Model):
|
||||
@classmethod
|
||||
def get_tracked_opening_type(cls, obj: bpy.types.Object) -> Union[Literal["OPENING", "BOOLEAN"], None]:
|
||||
"""Get tracked opening type, return `None` if object is not a tracked opening."""
|
||||
for opening in bpy.context.scene.BIMModelProperties.openings:
|
||||
props = cls.get_model_props()
|
||||
for opening in props.openings:
|
||||
if opening.obj == obj:
|
||||
return opening.name
|
||||
return None
|
||||
|
||||
@@ -143,7 +143,7 @@ class Project(bonsai.core.tool.Project):
|
||||
|
||||
@classmethod
|
||||
def set_default_modeling_dimensions(cls):
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
props.extrusion_depth = 3
|
||||
props.length = 1
|
||||
|
||||
@@ -35,7 +35,8 @@ class Root(bonsai.core.tool.Root):
|
||||
@classmethod
|
||||
def add_tracked_opening(cls, obj: bpy.types.Object, opening_type: Literal["OPENING", "BOOLEAN"]) -> None:
|
||||
"""Add tracked opening or boolean object."""
|
||||
new = bpy.context.scene.BIMModelProperties.openings.add()
|
||||
props = tool.Model.get_model_props()
|
||||
new = props.openings.add()
|
||||
new.obj = obj
|
||||
new.name = opening_type
|
||||
|
||||
|
||||
@@ -688,7 +688,8 @@ class Spatial(bonsai.core.tool.Spatial):
|
||||
|
||||
@classmethod
|
||||
def get_boundary_lines_from_context_visible_objects(cls) -> list[shapely.LineString]:
|
||||
calculation_rl = bpy.context.scene.BIMModelProperties.rl3
|
||||
props = props = tool.Model.get_model_props()
|
||||
calculation_rl = props.rl3
|
||||
container = tool.Root.get_default_container()
|
||||
container_obj = tool.Ifc.get_object(container)
|
||||
cut_point = container_obj.matrix_world.translation.copy() + Vector((0, 0, calculation_rl))
|
||||
@@ -1054,7 +1055,7 @@ class Spatial(bonsai.core.tool.Spatial):
|
||||
|
||||
@classmethod
|
||||
def get_relating_type_id(cls) -> int:
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
return relating_type_id
|
||||
|
||||
@@ -1110,7 +1111,8 @@ class Spatial(bonsai.core.tool.Spatial):
|
||||
|
||||
@classmethod
|
||||
def assign_type_to_obj(cls, obj: bpy.types.Object) -> None:
|
||||
relating_type_id = bpy.context.scene.BIMModelProperties.relating_type_id
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type_id = props.relating_type_id
|
||||
relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
ifc_class = relating_type.is_a()
|
||||
instance_class = ifcopenshell.util.type.get_applicable_entities(ifc_class, tool.Ifc.get().schema)[0]
|
||||
|
||||
@@ -360,7 +360,7 @@ def i_load_a_new_pset_template_file():
|
||||
|
||||
@given("I create default MEP types")
|
||||
def i_create_default_mep_types():
|
||||
model_props = bpy.context.scene.BIMModelProperties
|
||||
model_props = tool.Model.get_model_props()
|
||||
|
||||
# add couple segments types
|
||||
model_props.type_class = "IfcDuctSegmentType"
|
||||
@@ -1244,13 +1244,13 @@ def i_display_the_construction_type_browser():
|
||||
@given("I add the construction type")
|
||||
@when("I add the construction type")
|
||||
def i_add_the_active_construction_type():
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
bpy.ops.bim.add_constr_type_instance(relating_type_id=int(props.relating_type_id))
|
||||
|
||||
|
||||
@then(parsers.parse("construction type is {relating_type_name}"))
|
||||
def construction_type(relating_type_name):
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
relating_type = AuthoringData.relating_type_name_by_id(props.ifc_class, props.relating_type_id)
|
||||
assert relating_type == relating_type_name, f"Construction Type is a {relating_type}, not a {relating_type_name}"
|
||||
|
||||
@@ -1333,7 +1333,8 @@ def the_obj_layer_lenght_is_set_to(value):
|
||||
|
||||
print(50 * "@", bpy.context.selected_objects)
|
||||
|
||||
bpy.context.scene.BIMModelProperties.length = value
|
||||
props = tool.Model.get_model_props()
|
||||
props.length = value
|
||||
bpy.ops.bim.change_layer_length(length=value)
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import bpy
|
||||
import mathutils
|
||||
import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
from test.bim.bootstrap import NewFile
|
||||
@@ -107,7 +108,7 @@ class TestDeleteDrawingElements(NewFile):
|
||||
assert False
|
||||
except:
|
||||
pass
|
||||
assert not bpy.data.objects.get("Object")
|
||||
assert not bpy.data.objects["Object"]
|
||||
|
||||
|
||||
class TestDisableEditingDrawings(NewFile):
|
||||
@@ -141,9 +142,10 @@ class TestDisableEditingSheets(NewFile):
|
||||
class TestDisableEditingText(NewFile):
|
||||
def test_run(self):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
obj.BIMTextProperties.is_editing = True
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.is_editing = True
|
||||
subject.disable_editing_text(obj)
|
||||
assert obj.BIMTextProperties.is_editing == False
|
||||
assert props.is_editing == False
|
||||
|
||||
|
||||
class TestDisableEditingAssignedProduct(NewFile):
|
||||
@@ -194,7 +196,8 @@ class TestEnableEditingText(NewFile):
|
||||
def test_run(self):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
subject.enable_editing_text(obj)
|
||||
assert obj.BIMTextProperties.is_editing == True
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
assert props.is_editing == True
|
||||
|
||||
|
||||
class TestEnableEditingAssignedProduct(NewFile):
|
||||
@@ -238,7 +241,7 @@ class TestEnsureUniqueIdentification(NewFile):
|
||||
class TestExportTextLiteralAttributes(NewFile):
|
||||
def test_run(self):
|
||||
TestImportTextAttributes().test_run()
|
||||
assert subject.export_text_literal_attributes(bpy.data.objects.get("Object")) == [
|
||||
assert subject.export_text_literal_attributes(bpy.data.objects["Object"]) == [
|
||||
{
|
||||
"Literal": "Literal",
|
||||
"Path": "RIGHT",
|
||||
@@ -584,7 +587,8 @@ class TestImportTextAttributes(NewFile):
|
||||
element.ObjectType = "TEXT" # TODO: double check if it's valid to set this
|
||||
tool.Ifc.link(element, obj)
|
||||
subject.import_text_attributes(obj)
|
||||
literal_props = obj.BIMTextProperties.literals[0]
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
literal_props = props.literals[0]
|
||||
assert literal_props.attributes.get("Literal").string_value == "Literal"
|
||||
assert literal_props.attributes.get("Path").enum_value == "RIGHT"
|
||||
assert literal_props.attributes.get("BoxAlignment").string_value == "bottom-left"
|
||||
@@ -733,11 +737,12 @@ class TestUpdateTextValue(NewFile):
|
||||
TestGetTextLiteral().test_run()
|
||||
ifc = tool.Ifc.get()
|
||||
|
||||
obj = bpy.data.objects.get("Object")
|
||||
obj = bpy.data.objects["Object"]
|
||||
subject.update_text_value(obj)
|
||||
literal = obj.BIMTextProperties.literals[0]
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
literal = props.literals[0]
|
||||
|
||||
assert obj.BIMTextProperties.font_size == "2.5"
|
||||
assert props.font_size == "2.5"
|
||||
assert literal.value == "Literal"
|
||||
assert literal.box_alignment[:] == tuple([False] * 6 + [True] + [False] * 2)
|
||||
assert literal.ifc_definition_id == ifc.by_type("IfcTextLiteralWithExtent")[0].id()
|
||||
@@ -745,7 +750,7 @@ class TestUpdateTextValue(NewFile):
|
||||
def test_using_attribute_variables(self):
|
||||
TestGetTextLiteral().test_run()
|
||||
|
||||
obj = bpy.data.objects.get("Object")
|
||||
obj = bpy.data.objects["Object"]
|
||||
ifc = tool.Ifc.get()
|
||||
wall = ifc.createIfcWall(Name="Baz")
|
||||
label = ifc.by_type("IfcAnnotation")[0]
|
||||
@@ -754,12 +759,13 @@ class TestUpdateTextValue(NewFile):
|
||||
ifc.by_type("IfcTextLiteralWithExtent")[0].Literal = "Foo {{Name}} Bar"
|
||||
|
||||
subject.update_text_value(obj)
|
||||
assert obj.BIMTextProperties.literals[0].value == "Foo Baz Bar"
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
assert props.literals[0].value == "Foo Baz Bar"
|
||||
|
||||
def test_using_property_variables(self):
|
||||
TestGetTextLiteral().test_run()
|
||||
|
||||
obj = bpy.data.objects.get("Object")
|
||||
obj = bpy.data.objects["Object"]
|
||||
ifc = tool.Ifc.get()
|
||||
wall = ifc.createIfcWall()
|
||||
pset = ifcopenshell.api.run("pset.add_pset", ifc, name="Custom_Pset", product=wall)
|
||||
@@ -770,14 +776,16 @@ class TestUpdateTextValue(NewFile):
|
||||
ifc.by_type("IfcTextLiteralWithExtent")[0].Literal = "Foo {{Custom_Pset.Key}} Bar"
|
||||
|
||||
subject.update_text_value(obj)
|
||||
assert obj.BIMTextProperties.literals[0].value == "Foo Baz Bar"
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
assert props.literals[0].value == "Foo Baz Bar"
|
||||
|
||||
def test_update_text_font_size(self):
|
||||
TestGetTextLiteral().test_run()
|
||||
obj = bpy.data.objects.get("Object")
|
||||
obj = bpy.data.objects["Object"]
|
||||
with bpy.context.temp_override(active_object=obj):
|
||||
bpy.ops.bim.enable_editing_text()
|
||||
obj.BIMTextProperties.font_size = "7.0"
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
props.font_size = "7.0"
|
||||
bpy.ops.bim.edit_text()
|
||||
annotation_classes = ifcopenshell.util.element.get_pset(tool.Ifc.get_entity(obj), "EPset_Annotation", "Classes")
|
||||
assert "title" in annotation_classes
|
||||
@@ -786,11 +794,12 @@ class TestUpdateTextValue(NewFile):
|
||||
def test_add_second_literal(self, setup=True):
|
||||
if setup:
|
||||
TestGetTextLiteral().test_run()
|
||||
obj = bpy.data.objects.get("Object")
|
||||
obj = bpy.data.objects["Object"]
|
||||
with bpy.context.temp_override(active_object=obj):
|
||||
bpy.ops.bim.enable_editing_text()
|
||||
bpy.ops.bim.add_text_literal()
|
||||
literal = obj.BIMTextProperties.literals[1]
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
literal = props.literals[1]
|
||||
literal.attributes["Literal"].string_value = "test_value"
|
||||
bpy.ops.bim.edit_text()
|
||||
|
||||
@@ -802,8 +811,8 @@ class TestUpdateTextValue(NewFile):
|
||||
self.test_update_text_font_size() # sets font size to "7.0"
|
||||
self.test_add_second_literal(setup=False)
|
||||
|
||||
obj = bpy.data.objects.get("Object")
|
||||
props = obj.BIMTextProperties
|
||||
obj = bpy.data.objects["Object"]
|
||||
props = tool.Drawing.get_text_props(obj)
|
||||
assert obj is not None, obj
|
||||
with bpy.context.temp_override(active_object=obj):
|
||||
bpy.ops.bim.enable_editing_text()
|
||||
|
||||
@@ -41,13 +41,15 @@ class TestGenerateOccurrenceName(NewFile):
|
||||
def test_generating_based_on_class(self):
|
||||
ifc = ifcopenshell.file()
|
||||
element_type = ifc.createIfcWallType(Name="Foobar")
|
||||
bpy.context.scene.BIMModelProperties.occurrence_name_style = "CLASS"
|
||||
props = tool.Model.get_model_props()
|
||||
props.occurrence_name_style = "CLASS"
|
||||
assert subject.generate_occurrence_name(element_type, "IfcWall") == "Wall"
|
||||
|
||||
def test_generating_based_on_type_name(self):
|
||||
ifc = ifcopenshell.file()
|
||||
element_type = ifc.createIfcWallType()
|
||||
bpy.context.scene.BIMModelProperties.occurrence_name_style = "TYPE"
|
||||
props = tool.Model.get_model_props()
|
||||
props.occurrence_name_style = "TYPE"
|
||||
assert subject.generate_occurrence_name(element_type, "IfcWall") == "Unnamed"
|
||||
element_type.Name = "Foobar"
|
||||
assert subject.generate_occurrence_name(element_type, "IfcWall") == "Foobar"
|
||||
@@ -55,8 +57,9 @@ class TestGenerateOccurrenceName(NewFile):
|
||||
def test_generating_based_on_a_custom_function(self):
|
||||
ifc = ifcopenshell.file()
|
||||
element_type = ifc.createIfcWallType()
|
||||
bpy.context.scene.BIMModelProperties.occurrence_name_style = "CUSTOM"
|
||||
bpy.context.scene.BIMModelProperties.occurrence_name_function = '"Foobar"'
|
||||
props = tool.Model.get_model_props()
|
||||
props.occurrence_name_style = "CUSTOM"
|
||||
props.occurrence_name_function = '"Foobar"'
|
||||
assert subject.generate_occurrence_name(element_type, "IfcWall") == "Foobar"
|
||||
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ class TestSetDefaultModelingDimensions(NewFile):
|
||||
ifc.createIfcProject()
|
||||
ifcopenshell.api.run("unit.assign_unit", ifc)
|
||||
subject.set_default_modeling_dimensions()
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
assert props.extrusion_depth == 3
|
||||
assert props.length == 1
|
||||
assert props.rl1 == 0
|
||||
|
||||
@@ -34,7 +34,7 @@ class TestAddTrackedOpening(NewFile):
|
||||
def test_run(self):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
subject.add_tracked_opening(obj, "OPENING")
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
props = tool.Model.get_model_props()
|
||||
assert props.openings[0].obj == obj
|
||||
assert props.openings[0].name == "OPENING"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user