This commit is contained in:
Andrej730
2026-01-12 16:07:34 +05:00
parent 1f845569a5
commit 153de70a71
28 changed files with 352 additions and 320 deletions
+1
View File
@@ -1295,6 +1295,7 @@ class IfcImporter:
if element.is_a("IfcSpace"): if element.is_a("IfcSpace"):
obj.hide_set(True) obj.hide_set(True)
class IfcImportSettings: class IfcImportSettings:
""" """
Initialize only using `IfcImportSettings.factory()`. Initialize only using `IfcImportSettings.factory()`.
@@ -158,6 +158,7 @@ def menu_func(self, context):
if element and element.is_a("IfcAnnotation") and element.ObjectType in ["SECTION", "ELEVATION"]: if element and element.is_a("IfcAnnotation") and element.ObjectType in ["SECTION", "ELEVATION"]:
self.layout.operator("bim.activate_drawing_by_annotation", text="Go to Drawing") self.layout.operator("bim.activate_drawing_by_annotation", text="Go to Drawing")
def register(): def register():
if not bpy.app.background: if not bpy.app.background:
bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=False) bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=False)
@@ -353,13 +353,13 @@ class CreateDrawing(bpy.types.Operator):
# Clear any local camera setup and force viewport to use scene camera # Clear any local camera setup and force viewport to use scene camera
for area in context.screen.areas: for area in context.screen.areas:
if area.type == 'VIEW_3D': if area.type == "VIEW_3D":
for space in area.spaces: for space in area.spaces:
if space.type == 'VIEW_3D': if space.type == "VIEW_3D":
# Clear local camera to ensure we use scene.camera # Clear local camera to ensure we use scene.camera
space.use_local_camera = False space.use_local_camera = False
space.camera = context.scene.camera space.camera = context.scene.camera
space.region_3d.view_perspective = 'CAMERA' space.region_3d.view_perspective = "CAMERA"
print(f"Set viewport camera to: {context.scene.camera.name}") print(f"Set viewport camera to: {context.scene.camera.name}")
break break
@@ -3080,7 +3080,7 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
filename_ext = ".svg" filename_ext = ".svg"
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement) files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype='DIR_PATH') directory: bpy.props.StringProperty(subtype="DIR_PATH")
def _execute(self, context): def _execute(self, context):
# Handle both single and multiple file selection # Handle both single and multiple file selection
@@ -4307,7 +4307,6 @@ class ActivateDrawingByAnnotation(bpy.types.Operator, tool.Ifc.Operator):
# Found the drawing element! # Found the drawing element!
return rel.RelatingProduct return rel.RelatingProduct
return None return None
@@ -5260,10 +5259,7 @@ class FormatElementValueRow(bpy.types.Operator):
custom_expression: bpy.props.StringProperty( custom_expression: bpy.props.StringProperty(
name="Custom Expression", name="Custom Expression",
description=( description=("Custom expression using functions\n" "Use {{value}} as placeholder for the current row's value."),
"Custom expression using functions\n"
"Use {{value}} as placeholder for the current row's value."
),
default='concat({{value}}, " - additional text")', default='concat({{value}}, " - additional text")',
) )
@@ -5470,7 +5466,7 @@ class ApplyElementValueRowsToLiteral(bpy.types.Operator):
""" """
import re import re
pattern = r'\{\{[^}]+\}\}' pattern = r"\{\{[^}]+\}\}"
new_base_value = f"{{{{{new_element_key}}}}}" new_base_value = f"{{{{{new_element_key}}}}}"
updated_value = re.sub(pattern, new_base_value, old_formatted_value) updated_value = re.sub(pattern, new_base_value, old_formatted_value)
+6 -4
View File
@@ -714,7 +714,9 @@ class ElementValueRow(PropertyGroup):
) )
element_key: StringProperty( element_key: StringProperty(
name="Element Key", description="The element value key (e.g., 'id', 'Name', 'Pset_WallCommon.Reference')", default="" name="Element Key",
description="The element value key (e.g., 'id', 'Name', 'Pset_WallCommon.Reference')",
default="",
) )
formatted_value: StringProperty( formatted_value: StringProperty(
@@ -764,7 +766,7 @@ def get_category_items_with_counts(self, context):
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
text_element = element text_element = element
if hasattr(self, 'product_used'): if hasattr(self, "product_used"):
if self.product_used: if self.product_used:
element = tool.Ifc.get_entity(self.product_used) element = tool.Ifc.get_entity(self.product_used)
else: else:
@@ -845,14 +847,14 @@ class LiteralProps(PropertyGroup):
element_value_rows: CollectionProperty( element_value_rows: CollectionProperty(
name="Element Value Rows", name="Element Value Rows",
type=ElementValueRow, type=ElementValueRow,
description="Collection of element value rows for building the literal value" description="Collection of element value rows for building the literal value",
) )
category_for_adding: EnumProperty( category_for_adding: EnumProperty(
name="Category for Adding", name="Category for Adding",
items=get_category_items_with_counts, items=get_category_items_with_counts,
default=0, default=0,
description="Category to use when adding a new element value row" description="Category to use when adding a new element value row",
) )
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -115,9 +115,13 @@ def parse_markdown_it(text: str) -> list[dict[str, Union[str, None]]]:
if tokens[j].type == "inline": if tokens[j].type == "inline":
for child in tokens[j].children or []: for child in tokens[j].children or []:
if child.type == "softbreak": if child.type == "softbreak":
segments.append({"text": None, "url": None, "break": True, "bold": False, "italic": False}) segments.append(
{"text": None, "url": None, "break": True, "bold": False, "italic": False}
)
elif child.type == "html_inline" and child.content.strip().lower() == "<br>": elif child.type == "html_inline" and child.content.strip().lower() == "<br>":
segments.append({"text": None, "url": None, "break": True, "bold": False, "italic": False}) segments.append(
{"text": None, "url": None, "break": True, "bold": False, "italic": False}
)
elif child.type == "strong_open": elif child.type == "strong_open":
bold = True bold = True
elif child.type == "strong_close": elif child.type == "strong_close":
@@ -133,11 +137,27 @@ def parse_markdown_it(text: str) -> list[dict[str, Union[str, None]]]:
elif child.type == "link_close" and link_opening: elif child.type == "link_close" and link_opening:
url = link_opening.attrGet("href") url = link_opening.attrGet("href")
if url and link_text: if url and link_text:
segments.append({"text": link_text, "url": url, "break": False, "bold": bold, "italic": italic}) segments.append(
{
"text": link_text,
"url": url,
"break": False,
"bold": bold,
"italic": italic,
}
)
link_opening = None link_opening = None
link_text = None link_text = None
elif child.type == "text" and not link_opening: elif child.type == "text" and not link_opening:
segments.append({"text": child.content, "url": None, "break": False, "bold": bold, "italic": italic}) segments.append(
{
"text": child.content,
"url": None,
"break": False,
"bold": bold,
"italic": italic,
}
)
j += 1 j += 1
i = j i = j
else: else:
@@ -168,7 +188,9 @@ def parse_markdown_it(text: str) -> list[dict[str, Union[str, None]]]:
link_opening = None link_opening = None
link_text = None link_text = None
elif child.type == "text" and not link_opening: elif child.type == "text" and not link_opening:
segments.append({"text": child.content, "url": None, "break": False, "bold": bold, "italic": italic}) segments.append(
{"text": child.content, "url": None, "break": False, "bold": bold, "italic": italic}
)
i += 1 i += 1
segments = [seg for seg in segments if seg.get("text") is not None or seg.get("break", False)] segments = [seg for seg in segments if seg.get("text") is not None or seg.get("break", False)]
if not segments: if not segments:
@@ -260,7 +282,7 @@ class SvgWriter:
paths = self.resource_paths["Stylesheet"] paths = self.resource_paths["Stylesheet"]
if not paths: if not paths:
return return
path_list = [p.strip() for p in paths.split(',')] path_list = [p.strip() for p in paths.split(",")]
for path in path_list: for path in path_list:
if not os.path.exists(path): if not os.path.exists(path):
print(f"WARNING. Couldn't find stylesheet for the drawing by the path: {path}") print(f"WARNING. Couldn't find stylesheet for the drawing by the path: {path}")
+6 -3
View File
@@ -476,7 +476,6 @@ class BIM_PT_sheets(Panel):
op = row3.operator("bim.activate_drawing_from_sheet", icon="OUTLINER_OB_CAMERA", text="") op = row3.operator("bim.activate_drawing_from_sheet", icon="OUTLINER_OB_CAMERA", text="")
if active_sheet.reference_type == "DRAWING": if active_sheet.reference_type == "DRAWING":
drawingnamesvg = active_sheet.name drawingnamesvg = active_sheet.name
drawingname = drawingnamesvg.split(".svg")[0] drawingname = drawingnamesvg.split(".svg")[0]
@@ -712,7 +711,9 @@ class BIM_PT_text(Panel):
current_product = get_current_product_for_element_values(obj, literal_props) current_product = get_current_product_for_element_values(obj, literal_props)
product_name = current_product.name if (current_product and hasattr(current_product, "name")) else "Unknown" product_name = (
current_product.name if (current_product and hasattr(current_product, "name")) else "Unknown"
)
source_row = values_box.row() source_row = values_box.row()
source_row.label(text=f"Source: {product_name}", icon="OBJECT_DATA") source_row.label(text=f"Source: {product_name}", icon="OBJECT_DATA")
@@ -758,7 +759,9 @@ class BIM_PT_text(Panel):
apply_row = values_box.row() apply_row = values_box.row()
apply_row.scale_y = 1.2 apply_row.scale_y = 1.2
op = apply_row.operator("bim.apply_element_value_rows_to_literal", text="Apply to Literal", icon="CHECKMARK") op = apply_row.operator(
"bim.apply_element_value_rows_to_literal", text="Apply to Literal", icon="CHECKMARK"
)
op.literal_prop_id = i op.literal_prop_id = i
else: else:
error_row = values_box.row() error_row = values_box.row()
@@ -1274,7 +1274,7 @@ class OverrideDuplicateMove(bpy.types.Operator):
all_objects_to_select.add(part_obj) all_objects_to_select.add(part_obj)
# Deselect everything first # Deselect everything first
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action="DESELECT")
# Select all the duplicated objects # Select all the duplicated objects
for obj in all_objects_to_select: for obj in all_objects_to_select:
@@ -1666,11 +1666,13 @@ class RefreshLinkedAggregate(bpy.types.Operator, tool.Ifc.Operator):
# Get the new group # Get the new group
new_group_entity = next( new_group_entity = next(
(r.RelatingGroup (
for r in getattr(aggregate, "HasAssignments", []) or [] r.RelatingGroup
if r.is_a("IfcRelAssignsToGroup") for r in getattr(aggregate, "HasAssignments", []) or []
if self.group_name in r.RelatingGroup.Name), if r.is_a("IfcRelAssignsToGroup")
None if self.group_name in r.RelatingGroup.Name
),
None,
) )
if not new_group_entity: if not new_group_entity:
+5 -3
View File
@@ -246,7 +246,7 @@ class BIM_PT_object_material(Panel):
"layer": "Material Layers", "layer": "Material Layers",
"profile": "Material Profiles", "profile": "Material Profiles",
"constituent": "Material Constituents", "constituent": "Material Constituents",
"list_item": "Material List Items" "list_item": "Material List Items",
} }
header_text = header_map.get(set_item_name, "Material Items") header_text = header_map.get(set_item_name, "Material Items")
self.layout.label(text=header_text) self.layout.label(text=header_text)
@@ -395,6 +395,7 @@ class BIM_PT_object_material(Panel):
if unit_system == "IMPERIAL": if unit_system == "IMPERIAL":
precision = prefs.doc.imperial_precision precision = prefs.doc.imperial_precision
from bonsai.bim.module.drawing.helper import format_distance from bonsai.bim.module.drawing.helper import format_distance
formatted_offset = format_distance( formatted_offset = format_distance(
offset_value, precision=precision, suppress_zero_inches=True, in_unit_length=True offset_value, precision=precision, suppress_zero_inches=True, in_unit_length=True
) )
@@ -416,8 +417,9 @@ class BIM_PT_object_material(Panel):
if unit_system == "IMPERIAL": if unit_system == "IMPERIAL":
precision = prefs.doc.imperial_precision precision = prefs.doc.imperial_precision
from bonsai.bim.module.drawing.helper import format_distance from bonsai.bim.module.drawing.helper import format_distance
formatted_custom_offset = format_distance( formatted_custom_offset = format_distance(
pset_data['custom_offset'], precision=precision, suppress_zero_inches=True, in_unit_length=True pset_data["custom_offset"], precision=precision, suppress_zero_inches=True, in_unit_length=True
) )
box_row = box.row(align=True) box_row = box.row(align=True)
box_row.label(text="Custom Offset") box_row.label(text="Custom Offset")
@@ -436,7 +438,7 @@ class BIM_PT_object_material(Panel):
"layer": "Material Layers", "layer": "Material Layers",
"profile": "Material Profiles", "profile": "Material Profiles",
"constituent": "Material Constituents", "constituent": "Material Constituents",
"list_item": "Material List Items" "list_item": "Material List Items",
} }
header_text = header_map.get(set_item_name, "Material Items") header_text = header_map.get(set_item_name, "Material Items")
else: else:
+14 -14
View File
@@ -191,19 +191,19 @@ class FilledOpeningGenerator:
MappingSource=existing_mapping_source, MappingSource=existing_mapping_source,
MappingTarget=tool.Ifc.get().create_entity( MappingTarget=tool.Ifc.get().create_entity(
"IfcCartesianTransformationOperator3D", "IfcCartesianTransformationOperator3D",
Axis1=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(1., 0., 0.)), Axis1=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(1.0, 0.0, 0.0)),
Axis2=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 1., 0.)), Axis2=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0.0, 1.0, 0.0)),
LocalOrigin=tool.Ifc.get().create_entity("IfcCartesianPoint", Coordinates=(0., 0., 0.)), LocalOrigin=tool.Ifc.get().create_entity("IfcCartesianPoint", Coordinates=(0.0, 0.0, 0.0)),
Scale=1., Scale=1.0,
Axis3=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 0., 1.)) Axis3=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0.0, 0.0, 1.0)),
) ),
) )
mapped_representation = tool.Ifc.get().create_entity( mapped_representation = tool.Ifc.get().create_entity(
"IfcShapeRepresentation", "IfcShapeRepresentation",
ContextOfItems=context, ContextOfItems=context,
RepresentationIdentifier="Body", RepresentationIdentifier="Body",
RepresentationType="MappedRepresentation", RepresentationType="MappedRepresentation",
Items=[new_mapped_item] Items=[new_mapped_item],
) )
else: else:
mapped_representation = ifcopenshell.api.geometry.map_representation( mapped_representation = ifcopenshell.api.geometry.map_representation(
@@ -333,19 +333,19 @@ class FilledOpeningGenerator:
MappingSource=existing_mapping_source, MappingSource=existing_mapping_source,
MappingTarget=tool.Ifc.get().create_entity( MappingTarget=tool.Ifc.get().create_entity(
"IfcCartesianTransformationOperator3D", "IfcCartesianTransformationOperator3D",
Axis1=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(1., 0., 0.)), Axis1=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(1.0, 0.0, 0.0)),
Axis2=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 1., 0.)), Axis2=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0.0, 1.0, 0.0)),
LocalOrigin=tool.Ifc.get().create_entity("IfcCartesianPoint", Coordinates=(0., 0., 0.)), LocalOrigin=tool.Ifc.get().create_entity("IfcCartesianPoint", Coordinates=(0.0, 0.0, 0.0)),
Scale=1., Scale=1.0,
Axis3=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0., 0., 1.)) Axis3=tool.Ifc.get().create_entity("IfcDirection", DirectionRatios=(0.0, 0.0, 1.0)),
) ),
) )
mapped_representation = tool.Ifc.get().create_entity( mapped_representation = tool.Ifc.get().create_entity(
"IfcShapeRepresentation", "IfcShapeRepresentation",
ContextOfItems=context, ContextOfItems=context,
RepresentationIdentifier="Body", RepresentationIdentifier="Body",
RepresentationType="MappedRepresentation", RepresentationType="MappedRepresentation",
Items=[new_mapped_item] Items=[new_mapped_item],
) )
else: else:
mapped_representation = ifcopenshell.api.geometry.map_representation( mapped_representation = ifcopenshell.api.geometry.map_representation(
+5 -6
View File
@@ -397,10 +397,9 @@ class DumbSlabPlaner:
representation=representation, representation=representation,
) )
def update_extrusion_direction(
def update_extrusion_direction(element: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance, new_direction_ratios: tuple, obj: bpy.types.Object = None
new_direction_ratios: tuple, ) -> None:
obj: bpy.types.Object = None) -> None:
""" """
Update extrusion direction while preserving overall object orientation. Update extrusion direction while preserving overall object orientation.
@@ -824,7 +823,7 @@ class EnableEditingExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
tool.Model.import_profile(extrusion.SweptArea, obj=obj, position=position, x_angle=0) tool.Model.import_profile(extrusion.SweptArea, obj=obj, position=position, x_angle=0)
# Scale the Y coordinates by cos(rotation) to get horizontal projection # Scale the Y coordinates by cos(rotation) to get horizontal projection
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode="OBJECT")
for vert in obj.data.vertices: for vert in obj.data.vertices:
vert.co.y *= scale_factor vert.co.y *= scale_factor
else: else:
@@ -905,6 +904,7 @@ class EditExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
profile = tool.Model.export_profile(obj, position=position, x_angle=existing_x_angle) profile = tool.Model.export_profile(obj, position=position, x_angle=existing_x_angle)
if not profile: if not profile:
def msg(self, context): def msg(self, context):
self.layout.label(text="INVALID PROFILE") self.layout.label(text="INVALID PROFILE")
@@ -953,7 +953,6 @@ class EditExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
tool.Ifc.get(), product=element, representation=new_footprint tool.Ifc.get(), product=element, representation=new_footprint
) )
footprint_context = ifcopenshell.util.representation.get_context( footprint_context = ifcopenshell.util.representation.get_context(
tool.Ifc.get(), "Plan", "FootPrint", "SKETCH_VIEW" tool.Ifc.get(), "Plan", "FootPrint", "SKETCH_VIEW"
) )
+6 -2
View File
@@ -514,8 +514,12 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
if tool.Model.get_usage_type(element) == "LAYER3": if tool.Model.get_usage_type(element) == "LAYER3":
# For slabs, handle polyline scaling # For slabs, handle polyline scaling
existing_obj_x_angle = obj.rotation_euler.x existing_obj_x_angle = obj.rotation_euler.x
existing_obj_x_angle = 0 if tool.Cad.is_x(existing_obj_x_angle, 0, tolerance=0.001) else existing_obj_x_angle existing_obj_x_angle = (
existing_obj_x_angle = 0 if tool.Cad.is_x(existing_obj_x_angle, pi, tolerance=0.001) else existing_obj_x_angle 0 if tool.Cad.is_x(existing_obj_x_angle, 0, tolerance=0.001) else existing_obj_x_angle
)
existing_obj_x_angle = (
0 if tool.Cad.is_x(existing_obj_x_angle, pi, tolerance=0.001) else existing_obj_x_angle
)
# Scale the polyline coordinates # Scale the polyline coordinates
coord_list = builder.get_polyline_coords(extrusion.SweptArea.OuterCurve) coord_list = builder.get_polyline_coords(extrusion.SweptArea.OuterCurve)
@@ -3165,6 +3165,7 @@ class ImageScalingTool(bpy.types.Operator, PolylineOperator):
return {"FINISHED"} return {"FINISHED"}
class LoadBlendMetadataAndIFC(bpy.types.Operator): class LoadBlendMetadataAndIFC(bpy.types.Operator):
bl_idname = "bim.load_blend_metadata_and_ifc" bl_idname = "bim.load_blend_metadata_and_ifc"
bl_label = "Load Blend Metadata and IFC" bl_label = "Load Blend Metadata and IFC"
-2
View File
@@ -364,8 +364,6 @@ bpy.ops.wm.save_as_mainfile(filepath=r'{blendmetadata_path}')
return {"FINISHED"} return {"FINISHED"}
# TODO: Unused operator. # TODO: Unused operator.
# Is there a need for this or 'DIR_PATH' propety subtype does almost the same, # Is there a need for this or 'DIR_PATH' propety subtype does almost the same,
# but also has alt+click? # but also has alt+click?
+1 -1
View File
@@ -74,7 +74,7 @@ def _has_material_styles(ifc: type[tool.Ifc], element: ifcopenshell.entity_insta
# Check if any of the constituent materials have styles # Check if any of the constituent materials have styles
for material in materials: for material in materials:
if hasattr(material, 'HasRepresentation') and material.HasRepresentation: if hasattr(material, "HasRepresentation") and material.HasRepresentation:
return True return True
return False return False
+1 -1
View File
@@ -34,7 +34,6 @@ def assign_type(
type: ifcopenshell.entity_instance, type: ifcopenshell.entity_instance,
) -> None: ) -> None:
# Get the instance's current CardinalPoint before type assignment # Get the instance's current CardinalPoint before type assignment
instance_cardinal_point = None instance_cardinal_point = None
instance_material = ifcopenshell.util.element.get_material(element) instance_material = ifcopenshell.util.element.get_material(element)
@@ -54,6 +53,7 @@ def assign_type(
# Force representation regeneration # Force representation regeneration
from bonsai.bim.module.model.profile import DumbProfileRecalculator from bonsai.bim.module.model.profile import DumbProfileRecalculator
DumbProfileRecalculator().recalculate([obj]) DumbProfileRecalculator().recalculate([obj])
# for now, representation regeneration handled by API listeners # for now, representation regeneration handled by API listeners
else: else:
+1 -4
View File
@@ -386,10 +386,7 @@ class Blender(bonsai.core.tool.Blender):
# Add window if screen differs from current context # Add window if screen differs from current context
context = bpy.context context = bpy.context
if context and context.screen != screen: if context and context.screen != screen:
window = next( window = next((w for w in context.window_manager.windows if w.screen == screen), None)
(w for w in context.window_manager.windows if w.screen == screen),
None
)
if window: if window:
context_override["window"] = window context_override["window"] = window
+3 -2
View File
@@ -620,7 +620,6 @@ class Model(bonsai.core.tool.Model):
if not openings[i].obj: if not openings[i].obj:
openings.remove(i) openings.remove(i)
@classmethod @classmethod
def save_custom_offset_to_pset(cls, element: ifcopenshell.entity_instance, obj: bpy.types.Object) -> None: def save_custom_offset_to_pset(cls, element: ifcopenshell.entity_instance, obj: bpy.types.Object) -> None:
"""Save custom offset settings to BBIM_MaterialLayer pset.""" """Save custom offset settings to BBIM_MaterialLayer pset."""
@@ -718,7 +717,9 @@ class Model(bonsai.core.tool.Model):
) )
@classmethod @classmethod
def get_material_layer_custom_offset(cls, element: ifcopenshell.entity_instance, obj: bpy.types.Object) -> Optional[float]: def get_material_layer_custom_offset(
cls, element: ifcopenshell.entity_instance, obj: bpy.types.Object
) -> Optional[float]:
"""Get custom offset value, reading from pset if props are not set.""" """Get custom offset value, reading from pset if props are not set."""
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
layer_params = tool.Model.get_material_layer_parameters(element) layer_params = tool.Model.get_material_layer_parameters(element)
+23 -17
View File
@@ -533,21 +533,29 @@ class Project(bonsai.core.tool.Project):
doc = tool.Ifc.run("document.add_information", parent=None) doc = tool.Ifc.run("document.add_information", parent=None)
if ifc_file.schema == "IFC2X3": if ifc_file.schema == "IFC2X3":
tool.Ifc.run("document.edit_information", information=doc, attributes={ tool.Ifc.run(
"DocumentId": "BLEND_METADATA", "document.edit_information",
"Name": "Blend Metadata", information=doc,
"Scope": "BLEND_METADATA", attributes={
"Description": "References to blend metadata file for this IFC project", "DocumentId": "BLEND_METADATA",
"Location": metadata_filename "Name": "Blend Metadata",
}) "Scope": "BLEND_METADATA",
"Description": "References to blend metadata file for this IFC project",
"Location": metadata_filename,
},
)
else: else:
tool.Ifc.run("document.edit_information", information=doc, attributes={ tool.Ifc.run(
"Identification": "BLEND_METADATA", "document.edit_information",
"Name": "Blend Metadata", information=doc,
"Scope": "BLEND_METADATA", attributes={
"Description": "References to blend metadata file for this IFC project", "Identification": "BLEND_METADATA",
"Location": metadata_filename "Name": "Blend Metadata",
}) "Scope": "BLEND_METADATA",
"Description": "References to blend metadata file for this IFC project",
"Location": metadata_filename,
},
)
return doc return doc
@@ -561,9 +569,7 @@ class Project(bonsai.core.tool.Project):
if not ifc_file: if not ifc_file:
return return
tool.Ifc.run("document.edit_information", information=doc, attributes={ tool.Ifc.run("document.edit_information", information=doc, attributes={"Location": metadata_filename})
"Location": metadata_filename
})
@classmethod @classmethod
def remove_metadata_document_information(cls) -> None: def remove_metadata_document_information(cls) -> None:
@@ -1,4 +1,3 @@
import bonsai, json, bpy import bonsai, json, bpy
from pathlib import Path from pathlib import Path
@@ -11,14 +10,15 @@ settings_path = repo_root / ".vscode" / "settings.json"
settings_path.parent.mkdir(parents=True, exist_ok=True) settings_path.parent.mkdir(parents=True, exist_ok=True)
settings = json.loads(settings_path.read_text()) if settings_path.exists() else {} settings = json.loads(settings_path.read_text()) if settings_path.exists() else {}
settings.update({ settings.update(
"bonsai.localRoot": repo_path.as_posix(), {
"bonsai.remoteRoot": install_path.as_posix(), "bonsai.localRoot": repo_path.as_posix(),
"bonsai.blenderPath": Path(bpy.app.binary_path).parent.as_posix(), "bonsai.remoteRoot": install_path.as_posix(),
}) "bonsai.blenderPath": Path(bpy.app.binary_path).parent.as_posix(),
}
)
json_data = json.dumps(settings, indent=2) json_data = json.dumps(settings, indent=2)
settings_path.write_text(json_data) settings_path.write_text(json_data)
print("\n\nBonsai/VSCode development environment configured successfully!\n\n") print("\n\nBonsai/VSCode development environment configured successfully!\n\n")
@@ -107,10 +107,7 @@ class Usecase:
for p in self.polyline for p in self.polyline
] ]
else: else:
points = [ points = [(self.convert_si_to_unit(p[0]), self.convert_si_to_unit(p[1])) for p in self.polyline]
(self.convert_si_to_unit(p[0]), self.convert_si_to_unit(p[1]))
for p in self.polyline
]
if self.file.schema == "IFC2X3": if self.file.schema == "IFC2X3":
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points]) curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])