mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 03:33:48 +00:00
typing
This commit is contained in:
@@ -30,6 +30,7 @@ from bpy.props import (
|
|||||||
FloatVectorProperty,
|
FloatVectorProperty,
|
||||||
CollectionProperty,
|
CollectionProperty,
|
||||||
)
|
)
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
class BIMContextProperties(PropertyGroup):
|
class BIMContextProperties(PropertyGroup):
|
||||||
@@ -66,3 +67,10 @@ class BIMContextProperties(PropertyGroup):
|
|||||||
)
|
)
|
||||||
active_context_id: IntProperty(name="Active Context Id")
|
active_context_id: IntProperty(name="Active Context Id")
|
||||||
context_attributes: CollectionProperty(name="Context Attributes", type=Attribute)
|
context_attributes: CollectionProperty(name="Context Attributes", type=Attribute)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
contexts: str
|
||||||
|
subcontexts: str
|
||||||
|
target_views: str
|
||||||
|
active_context_id: int
|
||||||
|
context_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
|||||||
@@ -33,13 +33,14 @@ class BIM_PT_context(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get()
|
return bool(tool.Ifc.get())
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not ContextData.is_loaded:
|
if not ContextData.is_loaded:
|
||||||
ContextData.load()
|
ContextData.load()
|
||||||
|
|
||||||
props = context.scene.BIMContextProperties
|
assert self.layout
|
||||||
|
props = tool.Context.get_context_props()
|
||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.prop(props, "contexts", text="")
|
row.prop(props, "contexts", text="")
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ def update_cost_item_identification(self: "CostItem", context: bpy.types.Context
|
|||||||
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
|
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
|
||||||
)
|
)
|
||||||
if props.active_cost_item_id == self.ifc_definition_id:
|
if props.active_cost_item_id == self.ifc_definition_id:
|
||||||
attribute = props.cost_item_attributes.get("Identification")
|
attribute = props.cost_item_attributes["Identification"]
|
||||||
attribute.string_value = self.identification
|
attribute.string_value = self.identification
|
||||||
|
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ def update_cost_item_name(self: "CostItem", context: bpy.types.Context) -> None:
|
|||||||
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
|
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
|
||||||
)
|
)
|
||||||
if props.active_cost_item_id == self.ifc_definition_id:
|
if props.active_cost_item_id == self.ifc_definition_id:
|
||||||
attribute = props.cost_item_attributes.get("Name")
|
attribute = props.cost_item_attributes["Name"]
|
||||||
attribute.string_value = self.name
|
attribute.string_value = self.name
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,9 @@ class Annotator:
|
|||||||
def get_annotation_obj(
|
def get_annotation_obj(
|
||||||
drawing: ifcopenshell.entity_instance, object_type: str, data_type: tool.Drawing.ANNOTATION_DATA_TYPE
|
drawing: ifcopenshell.entity_instance, object_type: str, data_type: tool.Drawing.ANNOTATION_DATA_TYPE
|
||||||
) -> bpy.types.Object:
|
) -> bpy.types.Object:
|
||||||
|
assert bpy.context.scene
|
||||||
camera = tool.Ifc.get_object(drawing)
|
camera = tool.Ifc.get_object(drawing)
|
||||||
|
assert isinstance(camera, bpy.types.Object)
|
||||||
# those annotations you want to obey the depth of the 3d cursor
|
# those annotations you want to obey the depth of the 3d cursor
|
||||||
if object_type == "PLAN_LEVEL":
|
if object_type == "PLAN_LEVEL":
|
||||||
co1 = bpy.context.scene.cursor.location.copy()
|
co1 = bpy.context.scene.cursor.location.copy()
|
||||||
|
|||||||
@@ -1619,8 +1619,9 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = tool.Drawing.get_annotation_props()
|
props = tool.Drawing.get_annotation_props()
|
||||||
if not (drawing := tool.Ifc.get_entity(context.scene.camera)):
|
dprops = tool.Drawing.get_document_props()
|
||||||
self.report({"WARNING"}, "Not a BIM camera")
|
if not (drawing := dprops.get_active_drawing()):
|
||||||
|
self.report({"WARNING"}, "No active drawing.")
|
||||||
return
|
return
|
||||||
|
|
||||||
obj = core.add_annotation(
|
obj = core.add_annotation(
|
||||||
@@ -2643,6 +2644,7 @@ class ActivateDrawingStyle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def parse_filter_query(self, mode: Literal["INCLUDE", "EXCLUDE"], context: bpy.types.Context) -> None:
|
def parse_filter_query(self, mode: Literal["INCLUDE", "EXCLUDE"], context: bpy.types.Context) -> None:
|
||||||
if mode == "INCLUDE":
|
if mode == "INCLUDE":
|
||||||
|
assert context.scene
|
||||||
objects = context.scene.objects
|
objects = context.scene.objects
|
||||||
elif mode == "EXCLUDE":
|
elif mode == "EXCLUDE":
|
||||||
objects = context.visible_objects
|
objects = context.visible_objects
|
||||||
@@ -3103,6 +3105,7 @@ class OrderTextLiteralDown(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
# Ifc Operator is unnecessary, because suboperator is handling IFC changes.
|
||||||
class AssignSelectedObjectAsProduct(bpy.types.Operator):
|
class AssignSelectedObjectAsProduct(bpy.types.Operator):
|
||||||
bl_idname = "bim.assign_selected_as_product"
|
bl_idname = "bim.assign_selected_as_product"
|
||||||
bl_label = "Assign Selected Object As Product"
|
bl_label = "Assign Selected Object As Product"
|
||||||
@@ -3116,18 +3119,25 @@ class AssignSelectedObjectAsProduct(bpy.types.Operator):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
assert bpy.context.view_layer
|
||||||
objs = context.selected_objects[:]
|
objs = context.selected_objects[:]
|
||||||
obj1 = objs[0]
|
obj1, obj2 = objs
|
||||||
element1 = tool.Ifc.get_entity(obj1)
|
element1 = tool.Ifc.get_entity(obj1)
|
||||||
obj2 = objs[1]
|
|
||||||
element2 = tool.Ifc.get_entity(obj2)
|
element2 = tool.Ifc.get_entity(obj2)
|
||||||
|
assert element1 and element2
|
||||||
if element1.is_a("IfcAnnotation"):
|
if element1.is_a("IfcAnnotation"):
|
||||||
other_selected_object = obj2
|
other_selected_object = obj2
|
||||||
bpy.context.view_layer.objects.active = obj1
|
bpy.context.view_layer.objects.active = obj1
|
||||||
elif element2.is_a("IfcAnnotation"):
|
elif element2.is_a("IfcAnnotation"):
|
||||||
other_selected_object = obj1
|
other_selected_object = obj1
|
||||||
bpy.context.view_layer.objects.active = obj2
|
bpy.context.view_layer.objects.active = obj2
|
||||||
context.active_object.BIMAssignedProductProperties.relating_product = other_selected_object
|
else:
|
||||||
|
self.report({"ERROR"}, "One of the selected objects must be IfcAnnotation.")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
assert (active_obj := context.active_object)
|
||||||
|
props = tool.Drawing.get_object_assigned_product_props(active_obj)
|
||||||
|
props.relating_product = other_selected_object
|
||||||
bpy.ops.bim.edit_assigned_product()
|
bpy.ops.bim.edit_assigned_product()
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -3139,9 +3149,11 @@ class EditAssignedProduct(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
product = None
|
product = None
|
||||||
if context.active_object.BIMAssignedProductProperties.relating_product:
|
assert (obj := context.active_object)
|
||||||
product = tool.Ifc.get_entity(context.active_object.BIMAssignedProductProperties.relating_product)
|
props = tool.Drawing.get_object_assigned_product_props(obj)
|
||||||
core.edit_assigned_product(tool.Ifc, tool.Drawing, obj=context.active_object, product=product)
|
if props.relating_product:
|
||||||
|
product = tool.Ifc.get_entity(props.relating_product)
|
||||||
|
core.edit_assigned_product(tool.Ifc, tool.Drawing, obj=obj, product=product)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
|
|
||||||
@@ -3151,6 +3163,7 @@ class EnableEditingAssignedProduct(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
|
assert context.active_object
|
||||||
core.enable_editing_assigned_product(tool.Drawing, obj=context.active_object)
|
core.enable_editing_assigned_product(tool.Drawing, obj=context.active_object)
|
||||||
|
|
||||||
|
|
||||||
@@ -3160,6 +3173,7 @@ class DisableEditingAssignedProduct(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
|
assert context.active_object
|
||||||
core.disable_editing_assigned_product(tool.Drawing, obj=context.active_object)
|
core.disable_editing_assigned_product(tool.Drawing, obj=context.active_object)
|
||||||
|
|
||||||
|
|
||||||
@@ -3203,6 +3217,7 @@ class EditSheet(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
document_type: Literal["SHEET", "TITLEBLOCK", "EMBEDDED"]
|
document_type: Literal["SHEET", "TITLEBLOCK", "EMBEDDED"]
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
|
assert context.window_manager
|
||||||
self.props = tool.Drawing.get_document_props()
|
self.props = tool.Drawing.get_document_props()
|
||||||
sheet = tool.Ifc.get().by_id(self.props.sheets[self.props.active_sheet_index].ifc_definition_id)
|
sheet = tool.Ifc.get().by_id(self.props.sheets[self.props.active_sheet_index].ifc_definition_id)
|
||||||
if sheet.is_a("IfcDocumentInformation"):
|
if sheet.is_a("IfcDocumentInformation"):
|
||||||
|
|||||||
@@ -752,6 +752,12 @@ class LiteralProps(PropertyGroup):
|
|||||||
}
|
}
|
||||||
return text_data
|
return text_data
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
value: str
|
||||||
|
box_alignment: str
|
||||||
|
ifc_definition_id: int
|
||||||
|
|
||||||
|
|
||||||
class BIMTextProperties(PropertyGroup):
|
class BIMTextProperties(PropertyGroup):
|
||||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||||
@@ -802,6 +808,10 @@ class BIMAssignedProductProperties(PropertyGroup):
|
|||||||
is_editing_product: BoolProperty(name="Is Editing Product", default=False)
|
is_editing_product: BoolProperty(name="Is Editing Product", default=False)
|
||||||
relating_product: PointerProperty(name="Relating Product", type=bpy.types.Object, poll=relating_product_poll)
|
relating_product: PointerProperty(name="Relating Product", type=bpy.types.Object, poll=relating_product_poll)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
is_editing_product: bool
|
||||||
|
relating_product: Union[bpy.types.Object, None]
|
||||||
|
|
||||||
|
|
||||||
annotation_classes = [
|
annotation_classes = [
|
||||||
(x, *tool.Drawing.ANNOTATION_TYPES_DATA[x][:3], i) for i, x in enumerate(tool.Drawing.ANNOTATION_TYPES_DATA)
|
(x, *tool.Drawing.ANNOTATION_TYPES_DATA[x][:3], i) for i, x in enumerate(tool.Drawing.ANNOTATION_TYPES_DATA)
|
||||||
|
|||||||
@@ -494,17 +494,19 @@ class BIM_PT_product_assignments(Panel):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
if not tool.Ifc.get() or not context.active_object:
|
if not tool.Ifc.get() or not context.active_object:
|
||||||
return
|
return False
|
||||||
element = tool.Ifc.get_entity(context.active_object)
|
element = tool.Ifc.get_entity(context.active_object)
|
||||||
if not element:
|
if not element:
|
||||||
return
|
return False
|
||||||
return element.is_a("IfcAnnotation")
|
return element.is_a("IfcAnnotation")
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not ProductAssignmentsData.is_loaded:
|
if not ProductAssignmentsData.is_loaded:
|
||||||
ProductAssignmentsData.load()
|
ProductAssignmentsData.load()
|
||||||
|
|
||||||
props = context.active_object.BIMAssignedProductProperties
|
assert self.layout
|
||||||
|
assert (obj := context.active_object)
|
||||||
|
props = tool.Drawing.get_object_assigned_product_props(obj)
|
||||||
|
|
||||||
if props.is_editing_product:
|
if props.is_editing_product:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import ifcopenshell.util.placement
|
|||||||
import ifcopenshell.util.schema
|
import ifcopenshell.util.schema
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
|
from typing import Any, Union
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
|
|
||||||
|
|
||||||
@@ -45,13 +46,12 @@ class ViewportData:
|
|||||||
cls.data = {"mode": cls.mode()}
|
cls.data = {"mode": cls.mode()}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mode(cls):
|
def mode(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
obj_mode = ("OBJECT", "IFC Object Mode", "View and move the placements of objects", "OBJECT_DATAMODE", 0)
|
obj_mode = ("OBJECT", "IFC Object Mode", "View and move the placements of objects", "OBJECT_DATAMODE", 0)
|
||||||
item_mode = ("ITEM", "IFC Item Mode", "View individual representation items", "MESH_DATA", 1)
|
item_mode = ("ITEM", "IFC Item Mode", "View individual representation items", "MESH_DATA", 1)
|
||||||
edit_mode = ("EDIT", "IFC Edit Mode", "Edit representation items", "EDITMODE_HLT", 2)
|
edit_mode = ("EDIT", "IFC Edit Mode", "Edit representation items", "EDITMODE_HLT", 2)
|
||||||
|
|
||||||
obj = bpy.context.active_object
|
obj = bpy.context.active_object
|
||||||
element = tool.Ifc.get_entity(obj)
|
|
||||||
|
|
||||||
modes: list[tuple[str, str, str, str, int]] = [obj_mode]
|
modes: list[tuple[str, str, str, str, int]] = [obj_mode]
|
||||||
gprops = tool.Geometry.get_geometry_props()
|
gprops = tool.Geometry.get_geometry_props()
|
||||||
@@ -61,13 +61,14 @@ class ViewportData:
|
|||||||
if not obj:
|
if not obj:
|
||||||
return modes
|
return modes
|
||||||
|
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
pprops = tool.Project.get_project_props()
|
pprops = tool.Project.get_project_props()
|
||||||
if obj in pprops.clipping_planes_objs:
|
if obj in pprops.clipping_planes_objs:
|
||||||
pass
|
pass
|
||||||
elif element:
|
elif element:
|
||||||
if tool.Geometry.is_locked(element):
|
if tool.Geometry.is_locked(element):
|
||||||
pass
|
pass
|
||||||
elif obj.data and tool.Geometry.is_profile_based(obj.data):
|
elif obj.data and tool.Geometry.has_mesh_properties(obj.data) and tool.Geometry.is_profile_based(obj.data):
|
||||||
modes.append(edit_mode)
|
modes.append(edit_mode)
|
||||||
elif element.is_a("IfcRelSpaceBoundary"):
|
elif element.is_a("IfcRelSpaceBoundary"):
|
||||||
modes.append(edit_mode)
|
modes.append(edit_mode)
|
||||||
@@ -88,7 +89,7 @@ class ViewportData:
|
|||||||
|
|
||||||
|
|
||||||
class RepresentationsData:
|
class RepresentationsData:
|
||||||
data = {}
|
data: dict[str, Any] = {}
|
||||||
is_loaded = False
|
is_loaded = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -102,10 +103,12 @@ class RepresentationsData:
|
|||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def representations(cls):
|
def representations(cls) -> list[dict[str, Any]]:
|
||||||
results = []
|
results: list[dict[str, Any]] = []
|
||||||
obj = tool.Geometry.get_active_or_representation_obj()
|
obj = tool.Geometry.get_active_or_representation_obj()
|
||||||
|
assert obj
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
assert element
|
||||||
|
|
||||||
active_representation_id = None
|
active_representation_id = None
|
||||||
active_representation = tool.Geometry.get_active_representation(obj)
|
active_representation = tool.Geometry.get_active_representation(obj)
|
||||||
@@ -132,8 +135,8 @@ class RepresentationsData:
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def contexts(cls):
|
def contexts(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
results = []
|
results: list[tuple[str, str, str]] = []
|
||||||
for element in tool.Ifc.get().by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
for element in tool.Ifc.get().by_type("IfcGeometricRepresentationContext", include_subtypes=False):
|
||||||
results.append((str(element.id()), element.ContextType or "Unnamed", ""))
|
results.append((str(element.id()), element.ContextType or "Unnamed", ""))
|
||||||
for element in tool.Ifc.get().by_type("IfcGeometricRepresentationSubContext", include_subtypes=False):
|
for element in tool.Ifc.get().by_type("IfcGeometricRepresentationSubContext", include_subtypes=False):
|
||||||
@@ -219,9 +222,12 @@ class ConnectionsData:
|
|||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def connections(cls):
|
def connections(cls) -> list[dict[str, Any]]:
|
||||||
results = []
|
results: list[dict[str, Any]] = []
|
||||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
obj = bpy.context.active_object
|
||||||
|
assert obj
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
assert element
|
||||||
|
|
||||||
connected_to = getattr(element, "ConnectedTo", [])
|
connected_to = getattr(element, "ConnectedTo", [])
|
||||||
connected_from = getattr(element, "ConnectedFrom", [])
|
connected_from = getattr(element, "ConnectedFrom", [])
|
||||||
@@ -285,13 +291,16 @@ class ConnectionsData:
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_connection_realization(cls):
|
def is_connection_realization(cls) -> Union[list[dict[str, Any]], None]:
|
||||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
obj = bpy.context.active_object
|
||||||
|
assert obj
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
assert element
|
||||||
connections = getattr(element, "IsConnectionRealization", None)
|
connections = getattr(element, "IsConnectionRealization", None)
|
||||||
if not connections:
|
if not connections:
|
||||||
return
|
return
|
||||||
|
|
||||||
results = []
|
results: list[dict[str, Any]] = []
|
||||||
for rel in connections:
|
for rel in connections:
|
||||||
data = {
|
data = {
|
||||||
"realizing_elements_connection_type": rel.ConnectionType,
|
"realizing_elements_connection_type": rel.ConnectionType,
|
||||||
@@ -322,16 +331,19 @@ class DerivedCoordinatesData:
|
|||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_z_values(cls):
|
def load_z_values(cls) -> None:
|
||||||
cls.z_values = [
|
cls.z_values = [
|
||||||
(bpy.context.active_object.matrix_world @ Vector(co))[2] for co in bpy.context.active_object.bound_box
|
(bpy.context.active_object.matrix_world @ Vector(co))[2] for co in bpy.context.active_object.bound_box
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_collection(cls):
|
def load_collection(cls) -> None:
|
||||||
cls.collection = None
|
cls.collection = None
|
||||||
cls.collection_z = 0
|
cls.collection_z = 0
|
||||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
obj = bpy.context.active_object
|
||||||
|
if not obj:
|
||||||
|
return
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
return
|
return
|
||||||
parent = ifcopenshell.util.element.get_aggregate(element)
|
parent = ifcopenshell.util.element.get_aggregate(element)
|
||||||
@@ -392,7 +404,7 @@ class PlacementData:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls):
|
def load(cls):
|
||||||
cls.data = {"has_placement": cls.has_placement()}
|
cls.data: dict[str, Any] = {"has_placement": cls.has_placement()}
|
||||||
|
|
||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
obj = bpy.context.active_object
|
obj = bpy.context.active_object
|
||||||
@@ -415,13 +427,14 @@ class PlacementData:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def original_xyz(cls, obj):
|
def original_xyz(cls, obj: bpy.types.Object) -> list[float]:
|
||||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
|
translation = obj.matrix_world.translation
|
||||||
xyz = ifcopenshell.util.geolocation.xyz2enh(
|
xyz = ifcopenshell.util.geolocation.xyz2enh(
|
||||||
obj.matrix_world[0][3],
|
translation[0],
|
||||||
obj.matrix_world[1][3],
|
translation[1],
|
||||||
obj.matrix_world[2][3],
|
translation[2],
|
||||||
float(props.blender_offset_x) * unit_scale,
|
float(props.blender_offset_x) * unit_scale,
|
||||||
float(props.blender_offset_y) * unit_scale,
|
float(props.blender_offset_y) * unit_scale,
|
||||||
float(props.blender_offset_z) * unit_scale,
|
float(props.blender_offset_z) * unit_scale,
|
||||||
|
|||||||
@@ -112,7 +112,9 @@ def update_blender_coordinates(self: "BIMGeoreferenceProperties", context: bpy.t
|
|||||||
props.is_updating_coordinates = True
|
props.is_updating_coordinates = True
|
||||||
blender_coordinates = tool.Georeference.get_coordinates("blender")
|
blender_coordinates = tool.Georeference.get_coordinates("blender")
|
||||||
local_coordinates = ifcopenshell.util.geolocation.xyz2enh(
|
local_coordinates = ifcopenshell.util.geolocation.xyz2enh(
|
||||||
*blender_coordinates,
|
blender_coordinates[0],
|
||||||
|
blender_coordinates[1],
|
||||||
|
blender_coordinates[2],
|
||||||
float(props.blender_offset_x),
|
float(props.blender_offset_x),
|
||||||
float(props.blender_offset_y),
|
float(props.blender_offset_y),
|
||||||
float(props.blender_offset_z),
|
float(props.blender_offset_z),
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import ifcopenshell
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
|
from typing import Any, Union
|
||||||
from ifcopenshell.util.doc import get_entity_doc
|
from ifcopenshell.util.doc import get_entity_doc
|
||||||
|
|
||||||
|
|
||||||
@@ -31,42 +33,46 @@ def refresh():
|
|||||||
|
|
||||||
class RolesAddressesData:
|
class RolesAddressesData:
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_roles(cls, parent):
|
def get_roles(cls, parent: ifcopenshell.entity_instance) -> list[dict[str, Any]]:
|
||||||
results = []
|
props = tool.Owner.get_owner_props()
|
||||||
|
results: list[dict[str, Any]] = []
|
||||||
for role in parent.Roles or []:
|
for role in parent.Roles or []:
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"id": role.id(),
|
"id": role.id(),
|
||||||
"is_editing": bpy.context.scene.BIMOwnerProperties.active_role_id == role.id(),
|
"is_editing": props.active_role_id == role.id(),
|
||||||
"label": role.UserDefinedRole or role.Role,
|
"label": role.UserDefinedRole or role.Role,
|
||||||
"props": bpy.context.scene.BIMOwnerProperties.role_attributes,
|
"props": props.role_attributes,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_addresses(cls, parent):
|
def get_addresses(cls, parent: ifcopenshell.entity_instance) -> list[dict[str, Any]]:
|
||||||
results = []
|
props = tool.Owner.get_owner_props()
|
||||||
|
results: list[dict[str, Any]] = []
|
||||||
for address in parent.Addresses or []:
|
for address in parent.Addresses or []:
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"id": address.id(),
|
"id": address.id(),
|
||||||
"is_editing": bpy.context.scene.BIMOwnerProperties.active_address_id == address.id(),
|
"is_editing": props.active_address_id == address.id(),
|
||||||
"label": address.is_a(),
|
"label": address.is_a(),
|
||||||
"props": bpy.context.scene.BIMOwnerProperties.address_attributes,
|
"props": props.address_attributes,
|
||||||
"list_attributes": cls.get_address_list_attributes(address),
|
"list_attributes": cls.get_address_list_attributes(address),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_address_list_attributes(cls, address):
|
def get_address_list_attributes(cls, address: ifcopenshell.entity_instance) -> list[dict[str, Any]]:
|
||||||
results = []
|
results: list[dict[str, Any]] = []
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = tool.Owner.get_owner_props()
|
||||||
if address.is_a("IfcPostalAddress"):
|
if address.is_a("IfcPostalAddress"):
|
||||||
names = ["AddressLines"]
|
names = ["AddressLines"]
|
||||||
elif address.is_a("IfcTelecomAddress"):
|
elif address.is_a("IfcTelecomAddress"):
|
||||||
names = ["TelephoneNumbers", "FacsimileNumbers", "ElectronicMailAddresses", "MessagingIDs"]
|
names = ["TelephoneNumbers", "FacsimileNumbers", "ElectronicMailAddresses", "MessagingIDs"]
|
||||||
|
else:
|
||||||
|
assert False, f"Unexpected entity: {address}"
|
||||||
for name in names:
|
for name in names:
|
||||||
if name == "AddressLines":
|
if name == "AddressLines":
|
||||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.address_lines)]
|
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.address_lines)]
|
||||||
@@ -78,6 +84,8 @@ class RolesAddressesData:
|
|||||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.electronic_mail_addresses)]
|
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.electronic_mail_addresses)]
|
||||||
elif name == "MessagingIDs":
|
elif name == "MessagingIDs":
|
||||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.messaging_ids)]
|
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.messaging_ids)]
|
||||||
|
else:
|
||||||
|
assert False, f"Unexpected name: {name}"
|
||||||
results.append({"name": name, "items": items})
|
results.append({"name": name, "items": items})
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -92,14 +100,15 @@ class PeopleData(RolesAddressesData):
|
|||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_people(cls):
|
def get_people(cls) -> list[dict[str, Any]]:
|
||||||
people = []
|
props = tool.Owner.get_owner_props()
|
||||||
|
people: list[dict[str, Any]] = []
|
||||||
for person in tool.Ifc.get().by_type("IfcPerson"):
|
for person in tool.Ifc.get().by_type("IfcPerson"):
|
||||||
roles = cls.get_roles(person)
|
roles = cls.get_roles(person)
|
||||||
people.append(
|
people.append(
|
||||||
{
|
{
|
||||||
"id": person.id(),
|
"id": person.id(),
|
||||||
"props": bpy.context.scene.BIMOwnerProperties.person_attributes,
|
"props": props.person_attributes,
|
||||||
"name": cls.get_person_name(person),
|
"name": cls.get_person_name(person),
|
||||||
"roles_label": ", ".join([r["label"] for r in roles]),
|
"roles_label": ", ".join([r["label"] for r in roles]),
|
||||||
"is_editing": cls.get_person_is_editing(person),
|
"is_editing": cls.get_person_is_editing(person),
|
||||||
@@ -112,7 +121,7 @@ class PeopleData(RolesAddressesData):
|
|||||||
return people
|
return people
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_person_name(cls, person):
|
def get_person_name(cls, person: ifcopenshell.entity_instance) -> str:
|
||||||
if tool.Ifc.get_schema() == "IFC2X3":
|
if tool.Ifc.get_schema() == "IFC2X3":
|
||||||
name = person.Id
|
name = person.Id
|
||||||
else:
|
else:
|
||||||
@@ -124,20 +133,24 @@ class PeopleData(RolesAddressesData):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_person_is_editing(cls, person):
|
def get_person_is_editing(cls, person: ifcopenshell.entity_instance) -> bool:
|
||||||
return bpy.context.scene.BIMOwnerProperties.active_person_id == person.id()
|
props = tool.Owner.get_owner_props()
|
||||||
|
return props.active_person_id == person.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_person_list_attributes(cls, person):
|
def get_person_list_attributes(cls, person: ifcopenshell.entity_instance) -> list[dict[str, Any]]:
|
||||||
results = []
|
results: list[dict[str, Any]] = []
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = tool.Owner.get_owner_props()
|
||||||
for name in ["MiddleNames", "PrefixTitles", "SuffixTitles"]:
|
name: tool.Owner.PersonAttributeType
|
||||||
|
for name in ("MiddleNames", "PrefixTitles", "SuffixTitles"):
|
||||||
if name == "MiddleNames":
|
if name == "MiddleNames":
|
||||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.middle_names)]
|
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.middle_names)]
|
||||||
elif name == "PrefixTitles":
|
elif name == "PrefixTitles":
|
||||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.prefix_titles)]
|
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.prefix_titles)]
|
||||||
elif name == "SuffixTitles":
|
elif name == "SuffixTitles":
|
||||||
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.suffix_titles)]
|
items = [{"id": id, "prop": prop} for id, prop in enumerate(props.suffix_titles)]
|
||||||
|
else:
|
||||||
|
assert False, name
|
||||||
results.append({"name": name, "items": items})
|
results.append({"name": name, "items": items})
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -152,17 +165,18 @@ class OrganisationsData(RolesAddressesData):
|
|||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_organisations(cls):
|
def get_organisations(cls) -> list[dict[str, Any]]:
|
||||||
organisations = []
|
props = tool.Owner.get_owner_props()
|
||||||
|
organisations: list[dict[str, Any]] = []
|
||||||
for organisation in tool.Ifc.get().by_type("IfcOrganization"):
|
for organisation in tool.Ifc.get().by_type("IfcOrganization"):
|
||||||
roles = cls.get_roles(organisation)
|
roles = cls.get_roles(organisation)
|
||||||
organisations.append(
|
organisations.append(
|
||||||
{
|
{
|
||||||
"id": organisation.id(),
|
"id": organisation.id(),
|
||||||
"props": bpy.context.scene.BIMOwnerProperties.organisation_attributes,
|
"props": props.organisation_attributes,
|
||||||
"name": organisation.Name,
|
"name": organisation.Name,
|
||||||
"roles_label": ", ".join([r["label"] for r in roles]),
|
"roles_label": ", ".join([r["label"] for r in roles]),
|
||||||
"is_editing": bpy.context.scene.BIMOwnerProperties.active_organisation_id == organisation.id(),
|
"is_editing": props.active_organisation_id == organisation.id(),
|
||||||
"is_engaged": bool(organisation.Engages),
|
"is_engaged": bool(organisation.Engages),
|
||||||
"roles": roles,
|
"roles": roles,
|
||||||
"addresses": cls.get_addresses(organisation),
|
"addresses": cls.get_addresses(organisation),
|
||||||
@@ -186,26 +200,27 @@ class OwnerData:
|
|||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_user_person(cls):
|
def get_user_person(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcPerson")]
|
return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcPerson")]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_user_organisation(cls):
|
def get_user_organisation(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcOrganization")]
|
return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcOrganization")]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_add_user(cls):
|
def can_add_user(cls) -> bool:
|
||||||
return tool.Ifc.get().by_type("IfcPerson") and tool.Ifc.get().by_type("IfcOrganization")
|
return bool(tool.Ifc.get().by_type("IfcPerson") and tool.Ifc.get().by_type("IfcOrganization"))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_users(cls):
|
def get_users(cls) -> list[dict[str, Any]]:
|
||||||
results = []
|
props = tool.Owner.get_owner_props()
|
||||||
|
results: list[dict[str, Any]] = []
|
||||||
for user in tool.Ifc.get().by_type("IfcPersonAndOrganization"):
|
for user in tool.Ifc.get().by_type("IfcPersonAndOrganization"):
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"id": user.id(),
|
"id": user.id(),
|
||||||
"label": "{} ({})".format(user.ThePerson[0] or "Unnamed", user.TheOrganization[0] or "Unnamed"),
|
"label": "{} ({})".format(user.ThePerson[0] or "Unnamed", user.TheOrganization[0] or "Unnamed"),
|
||||||
"is_active": bpy.context.scene.BIMOwnerProperties.active_user_id == user.id(),
|
"is_active": props.active_user_id == user.id(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return results
|
return results
|
||||||
@@ -224,48 +239,60 @@ class ActorData:
|
|||||||
cls.data["actors"] = cls.actors()
|
cls.data["actors"] = cls.actors()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def the_actor(cls):
|
def the_actor(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not (ifc_class := bpy.context.scene.BIMOwnerProperties.actor_type):
|
props = tool.Owner.get_owner_props()
|
||||||
|
if not (ifc_class := props.actor_type):
|
||||||
ifc_class = cls.actor_type()[0][0]
|
ifc_class = cls.actor_type()[0][0]
|
||||||
return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type(ifc_class)]
|
return [(str(p.id()), p[0] or "Unnamed", "") for p in tool.Ifc.get().by_type(ifc_class)]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def actors(cls):
|
def actors(cls) -> list[dict[str, Any]]:
|
||||||
actors = []
|
actors: list[dict[str, Any]] = []
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = tool.Owner.get_owner_props()
|
||||||
for actor in tool.Ifc.get().by_type(props.actor_class, include_subtypes=False):
|
for actor in tool.Ifc.get().by_type(props.actor_class, include_subtypes=False):
|
||||||
is_editing = props.active_actor_id == actor.id()
|
is_editing = props.active_actor_id == actor.id()
|
||||||
if actor.TheActor.is_a("IfcPerson"):
|
the_actor: ifcopenshell.entity_instance = actor.TheActor
|
||||||
the_actor = actor.TheActor.Identification or "N/A"
|
if the_actor.is_a("IfcPerson"):
|
||||||
elif actor.TheActor.is_a("IfcOrganization"):
|
the_actor_ = the_actor.Identification or "N/A"
|
||||||
the_actor = actor.TheActor.Identification or "N/A"
|
elif the_actor.is_a("IfcOrganization"):
|
||||||
elif actor.TheActor.is_a("IfcPersonAndOrganization"):
|
the_actor_ = the_actor.Identification or "N/A"
|
||||||
the_actor = actor.TheActor.ThePerson.Identification or "N/A"
|
elif the_actor.is_a("IfcPersonAndOrganization"):
|
||||||
the_actor += "-" + actor.TheActor.TheOrganization.Identification or "N/A"
|
the_actor_ = the_actor.ThePerson.Identification or "N/A"
|
||||||
|
the_actor_ += "-" + the_actor.TheOrganization.Identification or "N/A"
|
||||||
|
else:
|
||||||
|
assert False, the_actor
|
||||||
actors.append(
|
actors.append(
|
||||||
{"id": actor.id(), "name": actor.Name or "Unnamed", "the_actor": the_actor, "is_editing": is_editing}
|
{
|
||||||
|
"id": actor.id(),
|
||||||
|
"name": actor.Name or "Unnamed",
|
||||||
|
"the_actor": the_actor_,
|
||||||
|
"is_editing": is_editing,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return actors
|
return actors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def actor_class(cls) -> list[tuple[str, str, str]]:
|
def actor_class(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
version = tool.Ifc.get_schema()
|
version = tool.Ifc.get_schema()
|
||||||
|
actor_doc = get_entity_doc(version, "IfcActor")
|
||||||
|
occupant_doc = get_entity_doc(version, "IfcOccupant")
|
||||||
|
assert actor_doc and occupant_doc
|
||||||
return [
|
return [
|
||||||
("IfcActor", "Actor", get_entity_doc(version, "IfcActor").get("description", "")),
|
("IfcActor", "Actor", actor_doc.get("description", "")),
|
||||||
("IfcOccupant", "Occupant", get_entity_doc(version, "IfcOccupant").get("description", "")),
|
("IfcOccupant", "Occupant", occupant_doc.get("description", "")),
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def actor_type(cls) -> list[tuple[str, str, str]]:
|
def actor_type(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
version = tool.Ifc.get_schema()
|
version = tool.Ifc.get_schema()
|
||||||
|
person_doc = get_entity_doc(version, "IfcPerson")
|
||||||
|
organization_doc = get_entity_doc(version, "IfcOrganization")
|
||||||
|
pao_doc = get_entity_doc(version, "IfcPersonAndOrganization")
|
||||||
|
assert person_doc and organization_doc and pao_doc
|
||||||
return [
|
return [
|
||||||
("IfcPerson", "Person", get_entity_doc(version, "IfcPerson").get("description", "")),
|
("IfcPerson", "Person", person_doc.get("description", "")),
|
||||||
("IfcOrganization", "Organisation", get_entity_doc(version, "IfcOrganization").get("description", "")),
|
("IfcOrganization", "Organisation", organization_doc.get("description", "")),
|
||||||
(
|
("IfcPersonAndOrganization", "User", pao_doc.get("description", "")),
|
||||||
"IfcPersonAndOrganization",
|
|
||||||
"User",
|
|
||||||
get_entity_doc(version, "IfcPersonAndOrganization").get("description", ""),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -279,25 +306,31 @@ class ObjectActorData:
|
|||||||
cls.data = {"actor": cls.actor(), "actors": cls.actors()}
|
cls.data = {"actor": cls.actor(), "actors": cls.actors()}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def actor(cls):
|
def actor(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
return [(str(p.id()), p.Name or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcActor")]
|
return [(str(p.id()), p.Name or "Unnamed", "") for p in tool.Ifc.get().by_type("IfcActor")]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def actors(cls):
|
def actors(cls) -> list[dict[str, Any]]:
|
||||||
results = []
|
results: list[dict[str, Any]] = []
|
||||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
obj = bpy.context.active_object
|
||||||
|
if not obj:
|
||||||
|
return results
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
return results
|
return results
|
||||||
for rel in getattr(element, "HasAssignments", []):
|
for rel in getattr(element, "HasAssignments", []):
|
||||||
if rel.is_a("IfcRelAssignsToActor"):
|
if rel.is_a("IfcRelAssignsToActor"):
|
||||||
actor = rel.RelatingActor
|
actor = rel.RelatingActor
|
||||||
if actor.TheActor.is_a("IfcPerson"):
|
the_actor: ifcopenshell.entity_instance = actor.TheActor
|
||||||
roles = cls.get_roles(actor.TheActor)
|
if the_actor.is_a("IfcPerson"):
|
||||||
elif actor.TheActor.is_a("IfcOrganization"):
|
roles = cls.get_roles(the_actor)
|
||||||
roles = cls.get_roles(actor.TheActor)
|
elif the_actor.is_a("IfcOrganization"):
|
||||||
elif actor.TheActor.is_a("IfcPersonAndOrganization"):
|
roles = cls.get_roles(the_actor)
|
||||||
roles = cls.get_roles(actor.TheActor.ThePerson)
|
elif the_actor.is_a("IfcPersonAndOrganization"):
|
||||||
roles.extend(cls.get_roles(actor.TheActor.TheOrganization))
|
roles = cls.get_roles(the_actor.ThePerson)
|
||||||
|
roles.extend(cls.get_roles(the_actor.TheOrganization))
|
||||||
|
else:
|
||||||
|
assert False, the_actor
|
||||||
role = ", ".join(roles)
|
role = ", ".join(roles)
|
||||||
results.append(
|
results.append(
|
||||||
{"id": actor.id(), "name": actor.Name or "Unnamed", "role": role, "ifc_class": actor.is_a()}
|
{"id": actor.id(), "name": actor.Name or "Unnamed", "role": role, "ifc_class": actor.is_a()}
|
||||||
@@ -305,5 +338,5 @@ class ObjectActorData:
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_roles(cls, parent):
|
def get_roles(cls, parent: ifcopenshell.entity_instance) -> list[Union[str, None]]:
|
||||||
return [r.UserDefinedRole or r.Role for r in parent.Roles or []]
|
return [r.UserDefinedRole or r.Role for r in parent.Roles or []]
|
||||||
|
|||||||
@@ -19,25 +19,35 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import bonsai.core.owner as core
|
import bonsai.core.owner as core
|
||||||
|
from ifcopenshell.api.owner.add_address import ADDRESS_TYPE
|
||||||
|
from typing import TYPE_CHECKING, get_args
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
import bpy._typing.rna_enums as rna_enums
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingPerson(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingPerson(bpy.types.Operator):
|
||||||
bl_idname = "bim.enable_editing_person"
|
bl_idname = "bim.enable_editing_person"
|
||||||
bl_label = "Enable Editing Person"
|
bl_label = "Enable Editing Person"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
person: bpy.props.IntProperty()
|
person: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
person: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.enable_editing_person(tool.Owner, person=tool.Ifc.get().by_id(self.person))
|
core.enable_editing_person(tool.Owner, person=tool.Ifc.get().by_id(self.person))
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingPerson(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingPerson(bpy.types.Operator):
|
||||||
bl_idname = "bim.disable_editing_person"
|
bl_idname = "bim.disable_editing_person"
|
||||||
bl_label = "Disable Editing Person"
|
bl_label = "Disable Editing Person"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.disable_editing_person(tool.Owner)
|
core.disable_editing_person(tool.Owner)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class AddPerson(bpy.types.Operator, tool.Ifc.Operator):
|
class AddPerson(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -45,7 +55,7 @@ class AddPerson(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_label = "Add Person"
|
bl_label = "Add Person"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context) -> None:
|
||||||
core.add_person(tool.Ifc)
|
core.add_person(tool.Ifc)
|
||||||
|
|
||||||
|
|
||||||
@@ -62,57 +72,81 @@ class RemovePerson(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.remove_person"
|
bl_idname = "bim.remove_person"
|
||||||
bl_label = "Remove Person"
|
bl_label = "Remove Person"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
person: bpy.props.IntProperty()
|
person: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
person: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.remove_person(tool.Ifc, person=tool.Ifc.get().by_id(self.person))
|
core.remove_person(tool.Ifc, person=tool.Ifc.get().by_id(self.person))
|
||||||
|
|
||||||
|
|
||||||
class AddPersonAttribute(bpy.types.Operator, tool.Ifc.Operator):
|
class AddPersonAttribute(bpy.types.Operator):
|
||||||
bl_idname = "bim.add_person_attribute"
|
bl_idname = "bim.add_person_attribute"
|
||||||
bl_label = "Add Person Attribute"
|
bl_label = "Add Person Attribute"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
name: bpy.props.StringProperty()
|
name: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration]
|
||||||
|
items=tuple((i, i, "") for i in get_args(tool.Owner.PersonAttributeType)),
|
||||||
|
)
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
name: tool.Owner.PersonAttributeType # pyright: ignore[reportIncompatibleVariableOverride]
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.add_person_attribute(tool.Owner, name=self.name)
|
core.add_person_attribute(tool.Owner, name=self.name)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class RemovePersonAttribute(bpy.types.Operator, tool.Ifc.Operator):
|
class RemovePersonAttribute(bpy.types.Operator):
|
||||||
bl_idname = "bim.remove_person_attribute"
|
bl_idname = "bim.remove_person_attribute"
|
||||||
bl_label = "Remove Person Attribute"
|
bl_label = "Remove Person Attribute"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
name: bpy.props.StringProperty()
|
name: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration]
|
||||||
id: bpy.props.IntProperty()
|
items=tuple((i, i, "") for i in get_args(tool.Owner.PersonAttributeType)),
|
||||||
|
)
|
||||||
|
id: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
name: tool.Owner.PersonAttributeType # pyright: ignore[reportIncompatibleVariableOverride]
|
||||||
|
id: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.remove_person_attribute(tool.Owner, name=self.name, id=self.id)
|
core.remove_person_attribute(tool.Owner, name=self.name, id=self.id)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingRole(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingRole(bpy.types.Operator):
|
||||||
bl_idname = "bim.enable_editing_role"
|
bl_idname = "bim.enable_editing_role"
|
||||||
bl_label = "Enable Editing Role"
|
bl_label = "Enable Editing Role"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
role: bpy.props.IntProperty()
|
role: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
role: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.enable_editing_role(tool.Owner, role=tool.Ifc.get().by_id(self.role))
|
core.enable_editing_role(tool.Owner, role=tool.Ifc.get().by_id(self.role))
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingRole(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingRole(bpy.types.Operator):
|
||||||
bl_idname = "bim.disable_editing_role"
|
bl_idname = "bim.disable_editing_role"
|
||||||
bl_label = "Disable Editing Role"
|
bl_label = "Disable Editing Role"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.disable_editing_role(tool.Owner)
|
core.disable_editing_role(tool.Owner)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class AddRole(bpy.types.Operator, tool.Ifc.Operator):
|
class AddRole(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.add_role"
|
bl_idname = "bim.add_role"
|
||||||
bl_label = "Add Role"
|
bl_label = "Add Role"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
parent: bpy.props.IntProperty()
|
parent: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
parent: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.add_role(tool.Ifc, parent=tool.Ifc.get().by_id(self.parent))
|
core.add_role(tool.Ifc, parent=tool.Ifc.get().by_id(self.parent))
|
||||||
@@ -131,7 +165,10 @@ class RemoveRole(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.remove_role"
|
bl_idname = "bim.remove_role"
|
||||||
bl_label = "Remove Role"
|
bl_label = "Remove Role"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
role: bpy.props.IntProperty()
|
role: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
role: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.remove_role(tool.Ifc, role=tool.Ifc.get().by_id(self.role))
|
core.remove_role(tool.Ifc, role=tool.Ifc.get().by_id(self.role))
|
||||||
@@ -141,51 +178,74 @@ class AddAddress(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.add_address"
|
bl_idname = "bim.add_address"
|
||||||
bl_label = "Add Address"
|
bl_label = "Add Address"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
parent: bpy.props.IntProperty()
|
parent: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
ifc_class: bpy.props.StringProperty()
|
ifc_class: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration]
|
||||||
|
items=tuple((i, i, "") for i in get_args(ADDRESS_TYPE)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
parent: int
|
||||||
|
ifc_class: ADDRESS_TYPE
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.add_address(tool.Ifc, parent=tool.Ifc.get().by_id(self.parent), ifc_class=self.ifc_class)
|
core.add_address(tool.Ifc, parent=tool.Ifc.get().by_id(self.parent), ifc_class=self.ifc_class)
|
||||||
|
|
||||||
|
|
||||||
class AddAddressAttribute(bpy.types.Operator, tool.Ifc.Operator):
|
class AddAddressAttribute(bpy.types.Operator):
|
||||||
bl_idname = "bim.add_address_attribute"
|
bl_idname = "bim.add_address_attribute"
|
||||||
bl_label = "Add Address Attribute"
|
bl_label = "Add Address Attribute"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
name: bpy.props.StringProperty()
|
name: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration]
|
||||||
|
items=tuple((i, i, "") for i in get_args(tool.Owner.AddressAttributeType)),
|
||||||
|
)
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
name: tool.Owner.AddressAttributeType # pyright: ignore[reportIncompatibleVariableOverride]
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.add_address_attribute(tool.Owner, name=self.name)
|
core.add_address_attribute(tool.Owner, name=self.name)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class RemoveAddressAttribute(bpy.types.Operator, tool.Ifc.Operator):
|
class RemoveAddressAttribute(bpy.types.Operator):
|
||||||
bl_idname = "bim.remove_address_attribute"
|
bl_idname = "bim.remove_address_attribute"
|
||||||
bl_label = "Remove Address Attribute"
|
bl_label = "Remove Address Attribute"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
name: bpy.props.StringProperty()
|
name: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration]
|
||||||
id: bpy.props.IntProperty()
|
items=tuple((i, i, "") for i in get_args(tool.Owner.AddressAttributeType)),
|
||||||
|
)
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
name: tool.Owner.AddressAttributeType # pyright: ignore[reportIncompatibleVariableOverride]
|
||||||
|
id: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.remove_address_attribute(tool.Owner, name=self.name, id=self.id)
|
core.remove_address_attribute(tool.Owner, name=self.name, id=self.id)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingAddress(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingAddress(bpy.types.Operator):
|
||||||
bl_idname = "bim.enable_editing_address"
|
bl_idname = "bim.enable_editing_address"
|
||||||
bl_label = "Enable Editing Address"
|
bl_label = "Enable Editing Address"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
address: bpy.props.IntProperty()
|
address: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
address: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.enable_editing_address(tool.Owner, address=tool.Ifc.get().by_id(self.address))
|
core.enable_editing_address(tool.Owner, address=tool.Ifc.get().by_id(self.address))
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingAddress(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingAddress(bpy.types.Operator):
|
||||||
bl_idname = "bim.disable_editing_address"
|
bl_idname = "bim.disable_editing_address"
|
||||||
bl_label = "Disable Editing Address"
|
bl_label = "Disable Editing Address"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.disable_editing_address(tool.Owner)
|
core.disable_editing_address(tool.Owner)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class EditAddress(bpy.types.Operator, tool.Ifc.Operator):
|
class EditAddress(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -201,29 +261,37 @@ class RemoveAddress(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.remove_address"
|
bl_idname = "bim.remove_address"
|
||||||
bl_label = "Remove Address"
|
bl_label = "Remove Address"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
address: bpy.props.IntProperty()
|
address: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
address: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.remove_address(tool.Ifc, address=tool.Ifc.get().by_id(self.address))
|
core.remove_address(tool.Ifc, address=tool.Ifc.get().by_id(self.address))
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingOrganisation(bpy.types.Operator):
|
||||||
bl_idname = "bim.enable_editing_organisation"
|
bl_idname = "bim.enable_editing_organisation"
|
||||||
bl_label = "Enable Editing Organisation"
|
bl_label = "Enable Editing Organisation"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
organisation: bpy.props.IntProperty()
|
organisation: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
organisation: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.enable_editing_organisation(tool.Owner, organisation=tool.Ifc.get().by_id(self.organisation))
|
core.enable_editing_organisation(tool.Owner, organisation=tool.Ifc.get().by_id(self.organisation))
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingOrganisation(bpy.types.Operator):
|
||||||
bl_idname = "bim.disable_editing_organisation"
|
bl_idname = "bim.disable_editing_organisation"
|
||||||
bl_label = "Disable Editing Organisation"
|
bl_label = "Disable Editing Organisation"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.disable_editing_organisation(tool.Owner)
|
core.disable_editing_organisation(tool.Owner)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class AddOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
class AddOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -248,7 +316,10 @@ class RemoveOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.remove_organisation"
|
bl_idname = "bim.remove_organisation"
|
||||||
bl_label = "Remove Organisation"
|
bl_label = "Remove Organisation"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
organisation: bpy.props.IntProperty()
|
organisation: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
organisation: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.remove_organisation(tool.Ifc, tool.Ifc.get().by_id(self.organisation))
|
core.remove_organisation(tool.Ifc, tool.Ifc.get().by_id(self.organisation))
|
||||||
@@ -258,8 +329,12 @@ class AddPersonAndOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.add_person_and_organisation"
|
bl_idname = "bim.add_person_and_organisation"
|
||||||
bl_label = "Add Person And Organisation"
|
bl_label = "Add Person And Organisation"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
person: bpy.props.IntProperty()
|
person: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
organisation: bpy.props.IntProperty()
|
organisation: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
person: int
|
||||||
|
organisation: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.add_person_and_organisation(
|
core.add_person_and_organisation(
|
||||||
@@ -271,7 +346,10 @@ class RemovePersonAndOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.remove_person_and_organisation"
|
bl_idname = "bim.remove_person_and_organisation"
|
||||||
bl_label = "Remove Person And Organisation"
|
bl_label = "Remove Person And Organisation"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
person_and_organisation: bpy.props.IntProperty()
|
person_and_organisation: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
person_and_organisation: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.remove_person_and_organisation(
|
core.remove_person_and_organisation(
|
||||||
@@ -279,24 +357,29 @@ class RemovePersonAndOrganisation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SetUser(bpy.types.Operator, tool.Ifc.Operator):
|
class SetUser(bpy.types.Operator):
|
||||||
bl_idname = "bim.set_user"
|
bl_idname = "bim.set_user"
|
||||||
bl_label = "Set User"
|
bl_label = "Set User"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
user: bpy.props.IntProperty()
|
user: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
user: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.set_user(tool.Owner, user=tool.Ifc.get().by_id(self.user))
|
core.set_user(tool.Owner, user=tool.Ifc.get().by_id(self.user))
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class ClearUser(bpy.types.Operator, tool.Ifc.Operator):
|
class ClearUser(bpy.types.Operator):
|
||||||
bl_idname = "bim.clear_user"
|
bl_idname = "bim.clear_user"
|
||||||
bl_label = "Clear User"
|
bl_label = "Clear User"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
user: bpy.props.IntProperty()
|
user: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.clear_user(tool.Owner)
|
core.clear_user(tool.Owner)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class AddActor(bpy.types.Operator, tool.Ifc.Operator):
|
class AddActor(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -305,28 +388,33 @@ class AddActor(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = tool.Owner.get_owner_props()
|
||||||
if props.the_actor:
|
if props.the_actor:
|
||||||
core.add_actor(tool.Ifc, ifc_class=props.actor_class, actor=tool.Ifc.get().by_id(int(props.the_actor)))
|
core.add_actor(tool.Ifc, ifc_class=props.actor_class, actor=tool.Ifc.get().by_id(int(props.the_actor)))
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingActor(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingActor(bpy.types.Operator):
|
||||||
bl_idname = "bim.enable_editing_actor"
|
bl_idname = "bim.enable_editing_actor"
|
||||||
bl_label = "Enable Editing Actor"
|
bl_label = "Enable Editing Actor"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
actor: bpy.props.IntProperty()
|
actor: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
def _execute(self, context):
|
if TYPE_CHECKING:
|
||||||
|
actor: int
|
||||||
|
|
||||||
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.enable_editing_actor(tool.Owner, actor=tool.Ifc.get().by_id(self.actor))
|
core.enable_editing_actor(tool.Owner, actor=tool.Ifc.get().by_id(self.actor))
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingActor(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingActor(bpy.types.Operator):
|
||||||
bl_idname = "bim.disable_editing_actor"
|
bl_idname = "bim.disable_editing_actor"
|
||||||
bl_label = "Disable Editing Actor"
|
bl_label = "Disable Editing Actor"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
core.disable_editing_actor(tool.Owner)
|
core.disable_editing_actor(tool.Owner)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class EditActor(bpy.types.Operator, tool.Ifc.Operator):
|
class EditActor(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -342,7 +430,10 @@ class RemoveActor(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.remove_actor"
|
bl_idname = "bim.remove_actor"
|
||||||
bl_label = "Remove Actor"
|
bl_label = "Remove Actor"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
actor: bpy.props.IntProperty()
|
actor: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
actor: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.remove_actor(tool.Ifc, actor=tool.Ifc.get().by_id(self.actor))
|
core.remove_actor(tool.Ifc, actor=tool.Ifc.get().by_id(self.actor))
|
||||||
@@ -352,21 +443,27 @@ class AssignActor(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.assign_actor"
|
bl_idname = "bim.assign_actor"
|
||||||
bl_label = "Assign Actor"
|
bl_label = "Assign Actor"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
actor: bpy.props.IntProperty()
|
actor: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
actor: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.assign_actor(
|
assert (obj := context.active_object)
|
||||||
tool.Ifc, actor=tool.Ifc.get().by_id(self.actor), element=tool.Ifc.get_entity(context.active_object)
|
assert (element := tool.Ifc.get_entity(obj))
|
||||||
)
|
core.assign_actor(tool.Ifc, actor=tool.Ifc.get().by_id(self.actor), element=element)
|
||||||
|
|
||||||
|
|
||||||
class UnassignActor(bpy.types.Operator, tool.Ifc.Operator):
|
class UnassignActor(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.unassign_actor"
|
bl_idname = "bim.unassign_actor"
|
||||||
bl_label = "Unassign Actor"
|
bl_label = "Unassign Actor"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
actor: bpy.props.IntProperty()
|
actor: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
actor: int
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.unassign_actor(
|
assert (obj := context.active_object)
|
||||||
tool.Ifc, actor=tool.Ifc.get().by_id(self.actor), element=tool.Ifc.get_entity(context.active_object)
|
assert (element := tool.Ifc.get_entity(obj))
|
||||||
)
|
core.unassign_actor(tool.Ifc, actor=tool.Ifc.get().by_id(self.actor), element=element)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import bpy
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bonsai.bim.prop import StrProperty, Attribute
|
from bonsai.bim.prop import StrProperty, Attribute
|
||||||
from bonsai.bim.module.owner.data import OwnerData, ActorData, ObjectActorData
|
from bonsai.bim.module.owner.data import OwnerData, ActorData, ObjectActorData
|
||||||
|
from typing import TYPE_CHECKING, Literal
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
PointerProperty,
|
PointerProperty,
|
||||||
@@ -33,45 +34,45 @@ from bpy.props import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_user_person(self, context):
|
def get_user_person(self: "BIMOwnerProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not OwnerData.is_loaded:
|
if not OwnerData.is_loaded:
|
||||||
OwnerData.load()
|
OwnerData.load()
|
||||||
return OwnerData.data["user_person"]
|
return OwnerData.data["user_person"]
|
||||||
|
|
||||||
|
|
||||||
def get_user_organisation(self, context):
|
def get_user_organisation(self: "BIMOwnerProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not OwnerData.is_loaded:
|
if not OwnerData.is_loaded:
|
||||||
OwnerData.load()
|
OwnerData.load()
|
||||||
return OwnerData.data["user_organisation"]
|
return OwnerData.data["user_organisation"]
|
||||||
|
|
||||||
|
|
||||||
def get_the_actor(self, context):
|
def get_the_actor(self: "BIMOwnerProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not ActorData.is_loaded:
|
if not ActorData.is_loaded:
|
||||||
ActorData.load()
|
ActorData.load()
|
||||||
return ActorData.data["the_actor"]
|
return ActorData.data["the_actor"]
|
||||||
|
|
||||||
|
|
||||||
def get_actor(self, context):
|
def get_actor(self: "BIMOwnerProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not ObjectActorData.is_loaded:
|
if not ObjectActorData.is_loaded:
|
||||||
ObjectActorData.load()
|
ObjectActorData.load()
|
||||||
return ObjectActorData.data["actor"]
|
return ObjectActorData.data["actor"]
|
||||||
|
|
||||||
|
|
||||||
def update_actor_type(self, context):
|
def update_actor_type(self: "BIMOwnerProperties", context: bpy.types.Context) -> None:
|
||||||
ActorData.data["the_actor"] = ActorData.the_actor()
|
ActorData.data["the_actor"] = ActorData.the_actor()
|
||||||
|
|
||||||
|
|
||||||
def update_actor_class(self, context):
|
def update_actor_class(self: "BIMOwnerProperties", context: bpy.types.Context) -> None:
|
||||||
ActorData.data["actors"] = ActorData.actors()
|
ActorData.data["actors"] = ActorData.actors()
|
||||||
|
|
||||||
|
|
||||||
def get_actor_class(self, context):
|
def get_actor_class(self: "BIMOwnerProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not ActorData.is_loaded:
|
if not ActorData.is_loaded:
|
||||||
ActorData.load()
|
ActorData.load()
|
||||||
return ActorData.data["actor_class"]
|
return ActorData.data["actor_class"]
|
||||||
|
|
||||||
|
|
||||||
def get_actor_type(self, context):
|
def get_actor_type(self: "BIMOwnerProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||||
if not ActorData.is_loaded:
|
if not ActorData.is_loaded:
|
||||||
ActorData.load()
|
ActorData.load()
|
||||||
return ActorData.data["actor_type"]
|
return ActorData.data["actor_type"]
|
||||||
@@ -119,3 +120,30 @@ class BIMOwnerProperties(PropertyGroup):
|
|||||||
items=get_the_actor, name="Actor", description="This entity represents an individual human being."
|
items=get_the_actor, name="Actor", description="This entity represents an individual human being."
|
||||||
)
|
)
|
||||||
actor: EnumProperty(items=get_actor, name="Actor")
|
actor: EnumProperty(items=get_actor, name="Actor")
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
active_person_id: int
|
||||||
|
person_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
middle_names: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
prefix_titles: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
suffix_titles: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
active_organisation_id: int
|
||||||
|
organisation_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
active_role_id: int
|
||||||
|
role_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
active_address_id: int
|
||||||
|
address_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
address_lines: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
telephone_numbers: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
facsimile_numbers: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
electronic_mail_addresses: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
messaging_ids: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||||
|
user_person: str
|
||||||
|
user_organisation: str
|
||||||
|
active_user_id: int
|
||||||
|
active_actor_id: int
|
||||||
|
actor_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||||
|
actor_class: Literal["IfcActor", "IfcOccupant"]
|
||||||
|
actor_type: str
|
||||||
|
the_actor: str
|
||||||
|
actor: str
|
||||||
|
|||||||
@@ -19,10 +19,11 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import bonsai.bim.helper
|
import bonsai.bim.helper
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
|
from typing import Any
|
||||||
from bonsai.bim.module.owner.data import PeopleData, OrganisationsData, OwnerData, ActorData, ObjectActorData
|
from bonsai.bim.module.owner.data import PeopleData, OrganisationsData, OwnerData, ActorData, ObjectActorData
|
||||||
|
|
||||||
|
|
||||||
def draw_roles(box, parent):
|
def draw_roles(box: bpy.types.UILayout, parent: dict[str, Any]) -> None:
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
row.label(text="Roles")
|
row.label(text="Roles")
|
||||||
op = row.operator("bim.add_role", icon="ADD", text="")
|
op = row.operator("bim.add_role", icon="ADD", text="")
|
||||||
@@ -41,7 +42,7 @@ def draw_roles(box, parent):
|
|||||||
row.operator("bim.remove_role", icon="X", text="").role = role["id"]
|
row.operator("bim.remove_role", icon="X", text="").role = role["id"]
|
||||||
|
|
||||||
|
|
||||||
def draw_addresses(box, parent):
|
def draw_addresses(box: bpy.types.UILayout, parent: dict[str, Any]) -> None:
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
row.label(text="Addresses")
|
row.label(text="Addresses")
|
||||||
op = row.operator("bim.add_address", icon="LINK_BLEND", text="")
|
op = row.operator("bim.add_address", icon="LINK_BLEND", text="")
|
||||||
@@ -87,12 +88,13 @@ class BIM_PT_people(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get()
|
return bool(tool.Ifc.get())
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not PeopleData.is_loaded:
|
if not PeopleData.is_loaded:
|
||||||
PeopleData.load()
|
PeopleData.load()
|
||||||
|
|
||||||
|
assert self.layout
|
||||||
self.layout.use_property_split = True
|
self.layout.use_property_split = True
|
||||||
self.layout.use_property_decorate = False
|
self.layout.use_property_decorate = False
|
||||||
|
|
||||||
@@ -102,7 +104,8 @@ class BIM_PT_people(bpy.types.Panel):
|
|||||||
for person in PeopleData.data["people"]:
|
for person in PeopleData.data["people"]:
|
||||||
self.draw_person(person)
|
self.draw_person(person)
|
||||||
|
|
||||||
def draw_person(self, person):
|
def draw_person(self, person: dict[str, Any]) -> None:
|
||||||
|
assert self.layout
|
||||||
if person["is_editing"]:
|
if person["is_editing"]:
|
||||||
box = self.layout.box()
|
box = self.layout.box()
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
@@ -146,12 +149,13 @@ class BIM_PT_organisations(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get()
|
return bool(tool.Ifc.get())
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not OrganisationsData.is_loaded:
|
if not OrganisationsData.is_loaded:
|
||||||
OrganisationsData.load()
|
OrganisationsData.load()
|
||||||
|
|
||||||
|
assert self.layout
|
||||||
self.layout.use_property_split = True
|
self.layout.use_property_split = True
|
||||||
self.layout.use_property_decorate = False
|
self.layout.use_property_decorate = False
|
||||||
|
|
||||||
@@ -161,7 +165,8 @@ class BIM_PT_organisations(bpy.types.Panel):
|
|||||||
for organisation in OrganisationsData.data["organisations"]:
|
for organisation in OrganisationsData.data["organisations"]:
|
||||||
self.draw_organisation(organisation)
|
self.draw_organisation(organisation)
|
||||||
|
|
||||||
def draw_organisation(self, organisation):
|
def draw_organisation(self, organisation: dict[str, Any]) -> None:
|
||||||
|
assert self.layout
|
||||||
if organisation["is_editing"]:
|
if organisation["is_editing"]:
|
||||||
box = self.layout.box()
|
box = self.layout.box()
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
@@ -193,15 +198,16 @@ class BIM_PT_owner(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get()
|
return bool(tool.Ifc.get())
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not OwnerData.is_loaded:
|
if not OwnerData.is_loaded:
|
||||||
OwnerData.load()
|
OwnerData.load()
|
||||||
|
|
||||||
|
assert self.layout
|
||||||
self.layout.use_property_split = True
|
self.layout.use_property_split = True
|
||||||
self.layout.use_property_decorate = False
|
self.layout.use_property_decorate = False
|
||||||
props = context.scene.BIMOwnerProperties
|
props = tool.Owner.get_owner_props()
|
||||||
|
|
||||||
if not OwnerData.data["user_person"]:
|
if not OwnerData.data["user_person"]:
|
||||||
self.layout.label(text="No people found.")
|
self.layout.label(text="No people found.")
|
||||||
@@ -244,13 +250,14 @@ class BIM_PT_actor(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get()
|
return bool(tool.Ifc.get())
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not ActorData.is_loaded:
|
if not ActorData.is_loaded:
|
||||||
ActorData.load()
|
ActorData.load()
|
||||||
|
|
||||||
self.props = context.scene.BIMOwnerProperties
|
assert self.layout
|
||||||
|
self.props = tool.Owner.get_owner_props()
|
||||||
|
|
||||||
self.layout.use_property_split = True
|
self.layout.use_property_split = True
|
||||||
self.layout.use_property_decorate = False
|
self.layout.use_property_decorate = False
|
||||||
@@ -268,7 +275,8 @@ class BIM_PT_actor(bpy.types.Panel):
|
|||||||
for actor in ActorData.data["actors"]:
|
for actor in ActorData.data["actors"]:
|
||||||
self.draw_actor(actor)
|
self.draw_actor(actor)
|
||||||
|
|
||||||
def draw_actor(self, actor):
|
def draw_actor(self, actor: dict[str, Any]) -> None:
|
||||||
|
assert self.layout
|
||||||
if actor["is_editing"]:
|
if actor["is_editing"]:
|
||||||
box = self.layout.box()
|
box = self.layout.box()
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
@@ -295,13 +303,14 @@ class BIM_PT_object_actor(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return tool.Ifc.get()
|
return bool(tool.Ifc.get())
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if not ObjectActorData.is_loaded:
|
if not ObjectActorData.is_loaded:
|
||||||
ObjectActorData.load()
|
ObjectActorData.load()
|
||||||
|
|
||||||
self.props = context.scene.BIMOwnerProperties
|
assert self.layout
|
||||||
|
self.props = tool.Owner.get_owner_props()
|
||||||
|
|
||||||
if not ObjectActorData.data["actor"]:
|
if not ObjectActorData.data["actor"]:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ def updateResourceName(self, context):
|
|||||||
attributes={"Name": self.name},
|
attributes={"Name": self.name},
|
||||||
)
|
)
|
||||||
if props.active_resource_id == self.ifc_definition_id:
|
if props.active_resource_id == self.ifc_definition_id:
|
||||||
attribute = props.resource_attributes.get("Name")
|
attribute = props.resource_attributes["Name"]
|
||||||
attribute.string_value = self.name
|
attribute.string_value = self.name
|
||||||
bonsai.bim.module.resource.data.refresh()
|
bonsai.bim.module.resource.data.refresh()
|
||||||
tool.Sequence.refresh_task_resources()
|
tool.Sequence.refresh_task_resources()
|
||||||
|
|||||||
@@ -27,167 +27,171 @@ if TYPE_CHECKING:
|
|||||||
from ifcopenshell.api.owner.add_actor import ACTOR_TYPE
|
from ifcopenshell.api.owner.add_actor import ACTOR_TYPE
|
||||||
|
|
||||||
|
|
||||||
def add_person(ifc: tool.Ifc) -> ifcopenshell.entity_instance:
|
def add_person(ifc: type[tool.Ifc]) -> ifcopenshell.entity_instance:
|
||||||
return ifc.run("owner.add_person")
|
return ifc.run("owner.add_person")
|
||||||
|
|
||||||
|
|
||||||
def remove_person(ifc: tool.Ifc, person: ifcopenshell.entity_instance) -> None:
|
def remove_person(ifc: type[tool.Ifc], person: ifcopenshell.entity_instance) -> None:
|
||||||
ifc.run("owner.remove_person", person=person)
|
ifc.run("owner.remove_person", person=person)
|
||||||
|
|
||||||
|
|
||||||
def enable_editing_person(owner: tool.Owner, person: ifcopenshell.entity_instance) -> None:
|
def enable_editing_person(owner: type[tool.Owner], person: ifcopenshell.entity_instance) -> None:
|
||||||
owner.set_person(person)
|
owner.set_person(person)
|
||||||
owner.import_person_attributes()
|
owner.import_person_attributes()
|
||||||
|
|
||||||
|
|
||||||
def disable_editing_person(owner: tool.Owner) -> None:
|
def disable_editing_person(owner: type[tool.Owner]) -> None:
|
||||||
owner.clear_person()
|
owner.clear_person()
|
||||||
|
|
||||||
|
|
||||||
def edit_person(ifc: tool.Ifc, owner: tool.Owner) -> None:
|
def edit_person(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> None:
|
||||||
ifc.run("owner.edit_person", person=owner.get_person(), attributes=owner.export_person_attributes())
|
ifc.run("owner.edit_person", person=owner.get_person(), attributes=owner.export_person_attributes())
|
||||||
disable_editing_person(owner)
|
disable_editing_person(owner)
|
||||||
|
|
||||||
|
|
||||||
def add_person_attribute(owner: tool.Owner, name: str) -> None:
|
def add_person_attribute(owner: type[tool.Owner], name: tool.Owner.PersonAttributeType) -> None:
|
||||||
owner.add_person_attribute(name)
|
owner.add_person_attribute(name)
|
||||||
|
|
||||||
|
|
||||||
def remove_person_attribute(owner: tool.Owner, name: str, id: int) -> None:
|
def remove_person_attribute(owner: type[tool.Owner], name: tool.Owner.PersonAttributeType, id: int) -> None:
|
||||||
owner.remove_person_attribute(name, id)
|
owner.remove_person_attribute(name, id)
|
||||||
|
|
||||||
|
|
||||||
def add_role(ifc: tool.Ifc, parent: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
def add_role(ifc: type[tool.Ifc], parent: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||||
return ifc.run("owner.add_role", assigned_object=parent)
|
return ifc.run("owner.add_role", assigned_object=parent)
|
||||||
|
|
||||||
|
|
||||||
def remove_role(ifc: tool.Ifc, role: ifcopenshell.entity_instance) -> None:
|
def remove_role(ifc: type[tool.Ifc], role: ifcopenshell.entity_instance) -> None:
|
||||||
ifc.run("owner.remove_role", role=role)
|
ifc.run("owner.remove_role", role=role)
|
||||||
|
|
||||||
|
|
||||||
def enable_editing_role(owner: tool.Owner, role: ifcopenshell.entity_instance) -> None:
|
def enable_editing_role(owner: type[tool.Owner], role: ifcopenshell.entity_instance) -> None:
|
||||||
owner.set_role(role)
|
owner.set_role(role)
|
||||||
owner.import_role_attributes()
|
owner.import_role_attributes()
|
||||||
|
|
||||||
|
|
||||||
def disable_editing_role(owner: tool.Owner) -> None:
|
def disable_editing_role(owner: type[tool.Owner]) -> None:
|
||||||
owner.clear_role()
|
owner.clear_role()
|
||||||
|
|
||||||
|
|
||||||
def edit_role(ifc: tool.Ifc, owner: tool.Owner) -> None:
|
def edit_role(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> None:
|
||||||
ifc.run("owner.edit_role", role=owner.get_role(), attributes=owner.export_role_attributes())
|
ifc.run("owner.edit_role", role=owner.get_role(), attributes=owner.export_role_attributes())
|
||||||
owner.clear_role()
|
owner.clear_role()
|
||||||
|
|
||||||
|
|
||||||
def add_address(
|
def add_address(
|
||||||
ifc: tool.Ifc, parent: ifcopenshell.entity_instance, ifc_class: ADDRESS_TYPE = "IfcPostalAddress"
|
ifc: type[tool.Ifc], parent: ifcopenshell.entity_instance, ifc_class: ADDRESS_TYPE = "IfcPostalAddress"
|
||||||
) -> ifcopenshell.entity_instance:
|
) -> ifcopenshell.entity_instance:
|
||||||
return ifc.run("owner.add_address", assigned_object=parent, ifc_class=ifc_class)
|
return ifc.run("owner.add_address", assigned_object=parent, ifc_class=ifc_class)
|
||||||
|
|
||||||
|
|
||||||
def remove_address(ifc: tool.Ifc, address: ifcopenshell.entity_instance) -> None:
|
def remove_address(ifc: type[tool.Ifc], address: ifcopenshell.entity_instance) -> None:
|
||||||
ifc.run("owner.remove_address", address=address)
|
ifc.run("owner.remove_address", address=address)
|
||||||
|
|
||||||
|
|
||||||
def enable_editing_address(owner: tool.Owner, address: ifcopenshell.entity_instance) -> None:
|
def enable_editing_address(owner: type[tool.Owner], address: ifcopenshell.entity_instance) -> None:
|
||||||
owner.set_address(address)
|
owner.set_address(address)
|
||||||
owner.import_address_attributes()
|
owner.import_address_attributes()
|
||||||
|
|
||||||
|
|
||||||
def disable_editing_address(owner: tool.Owner) -> None:
|
def disable_editing_address(owner: type[tool.Owner]) -> None:
|
||||||
owner.clear_address()
|
owner.clear_address()
|
||||||
|
|
||||||
|
|
||||||
def edit_address(ifc: tool.Ifc, owner: tool.Owner) -> None:
|
def edit_address(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> None:
|
||||||
address = owner.get_address()
|
address = owner.get_address()
|
||||||
ifc.run("owner.edit_address", address=address, attributes=owner.export_address_attributes())
|
ifc.run("owner.edit_address", address=address, attributes=owner.export_address_attributes())
|
||||||
owner.clear_address()
|
owner.clear_address()
|
||||||
|
|
||||||
|
|
||||||
def add_address_attribute(owner: tool.Owner, name: str) -> None:
|
def add_address_attribute(owner: type[tool.Owner], name: tool.Owner.AddressAttributeType) -> None:
|
||||||
owner.add_address_attribute(name)
|
owner.add_address_attribute(name)
|
||||||
|
|
||||||
|
|
||||||
def remove_address_attribute(owner: tool.Owner, name: str, id: int) -> None:
|
def remove_address_attribute(owner: type[tool.Owner], name: tool.Owner.AddressAttributeType, id: int) -> None:
|
||||||
owner.remove_address_attribute(name, id)
|
owner.remove_address_attribute(name, id)
|
||||||
|
|
||||||
|
|
||||||
def add_organisation(ifc: tool.Ifc) -> ifcopenshell.entity_instance:
|
def add_organisation(ifc: type[tool.Ifc]) -> ifcopenshell.entity_instance:
|
||||||
return ifc.run("owner.add_organisation")
|
return ifc.run("owner.add_organisation")
|
||||||
|
|
||||||
|
|
||||||
def remove_organisation(ifc: tool.Ifc, organisation: ifcopenshell.entity_instance) -> None:
|
def remove_organisation(ifc: type[tool.Ifc], organisation: ifcopenshell.entity_instance) -> None:
|
||||||
ifc.run("owner.remove_organisation", organisation=organisation)
|
ifc.run("owner.remove_organisation", organisation=organisation)
|
||||||
|
|
||||||
|
|
||||||
def enable_editing_organisation(owner: tool.Owner, organisation: ifcopenshell.entity_instance) -> None:
|
def enable_editing_organisation(owner: type[tool.Owner], organisation: ifcopenshell.entity_instance) -> None:
|
||||||
owner.set_organisation(organisation)
|
owner.set_organisation(organisation)
|
||||||
owner.import_organisation_attributes()
|
owner.import_organisation_attributes()
|
||||||
|
|
||||||
|
|
||||||
def disable_editing_organisation(owner: tool.Owner) -> None:
|
def disable_editing_organisation(owner: type[tool.Owner]) -> None:
|
||||||
owner.clear_organisation()
|
owner.clear_organisation()
|
||||||
|
|
||||||
|
|
||||||
def edit_organisation(ifc: tool.Ifc, owner: tool.Owner) -> None:
|
def edit_organisation(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> None:
|
||||||
organisation = owner.get_organisation()
|
organisation = owner.get_organisation()
|
||||||
ifc.run("owner.edit_organisation", organisation=organisation, attributes=owner.export_organisation_attributes())
|
ifc.run("owner.edit_organisation", organisation=organisation, attributes=owner.export_organisation_attributes())
|
||||||
owner.clear_organisation()
|
owner.clear_organisation()
|
||||||
|
|
||||||
|
|
||||||
def add_person_and_organisation(
|
def add_person_and_organisation(
|
||||||
ifc: tool.Ifc, person: ifcopenshell.entity_instance, organisation: ifcopenshell.entity_instance
|
ifc: type[tool.Ifc], person: ifcopenshell.entity_instance, organisation: ifcopenshell.entity_instance
|
||||||
) -> ifcopenshell.entity_instance:
|
) -> ifcopenshell.entity_instance:
|
||||||
return ifc.run("owner.add_person_and_organisation", person=person, organisation=organisation)
|
return ifc.run("owner.add_person_and_organisation", person=person, organisation=organisation)
|
||||||
|
|
||||||
|
|
||||||
def remove_person_and_organisation(
|
def remove_person_and_organisation(
|
||||||
ifc: tool.Ifc, owner: tool.Owner, person_and_organisation: ifcopenshell.entity_instance
|
ifc: type[tool.Ifc], owner: type[tool.Owner], person_and_organisation: ifcopenshell.entity_instance
|
||||||
) -> None:
|
) -> None:
|
||||||
if owner.get_user() == person_and_organisation:
|
if owner.get_user() == person_and_organisation:
|
||||||
owner.clear_user()
|
owner.clear_user()
|
||||||
ifc.run("owner.remove_person_and_organisation", person_and_organisation=person_and_organisation)
|
ifc.run("owner.remove_person_and_organisation", person_and_organisation=person_and_organisation)
|
||||||
|
|
||||||
|
|
||||||
def set_user(owner: tool.Owner, user: ifcopenshell.entity_instance) -> None:
|
def set_user(owner: type[tool.Owner], user: ifcopenshell.entity_instance) -> None:
|
||||||
owner.set_user(user)
|
owner.set_user(user)
|
||||||
|
|
||||||
|
|
||||||
def get_user(owner: tool.Owner) -> Union[ifcopenshell.entity_instance, None]:
|
def get_user(owner: type[tool.Owner]) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
return owner.get_user()
|
return owner.get_user()
|
||||||
|
|
||||||
|
|
||||||
def clear_user(owner: tool.Owner) -> None:
|
def clear_user(owner: type[tool.Owner]) -> None:
|
||||||
owner.clear_user()
|
owner.clear_user()
|
||||||
|
|
||||||
|
|
||||||
def add_actor(
|
def add_actor(
|
||||||
ifc: tool.Ifc, ifc_class: ACTOR_TYPE, actor: ifcopenshell.entity_instance
|
ifc: type[tool.Ifc], ifc_class: ACTOR_TYPE, actor: ifcopenshell.entity_instance
|
||||||
) -> ifcopenshell.entity_instance:
|
) -> ifcopenshell.entity_instance:
|
||||||
return ifc.run("owner.add_actor", ifc_class=ifc_class, actor=actor)
|
return ifc.run("owner.add_actor", ifc_class=ifc_class, actor=actor)
|
||||||
|
|
||||||
|
|
||||||
def remove_actor(ifc: tool.Ifc, actor: ifcopenshell.entity_instance) -> None:
|
def remove_actor(ifc: type[tool.Ifc], actor: ifcopenshell.entity_instance) -> None:
|
||||||
ifc.run("owner.remove_actor", actor=actor)
|
ifc.run("owner.remove_actor", actor=actor)
|
||||||
|
|
||||||
|
|
||||||
def enable_editing_actor(owner: tool.Owner, actor: ifcopenshell.entity_instance) -> None:
|
def enable_editing_actor(owner: type[tool.Owner], actor: ifcopenshell.entity_instance) -> None:
|
||||||
owner.set_actor(actor)
|
owner.set_actor(actor)
|
||||||
owner.import_actor_attributes(actor)
|
owner.import_actor_attributes(actor)
|
||||||
|
|
||||||
|
|
||||||
def disable_editing_actor(owner: tool.Owner) -> None:
|
def disable_editing_actor(owner: type[tool.Owner]) -> None:
|
||||||
owner.clear_actor()
|
owner.clear_actor()
|
||||||
|
|
||||||
|
|
||||||
def edit_actor(ifc: tool.Ifc, owner: tool.Owner) -> None:
|
def edit_actor(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> None:
|
||||||
ifc.run("owner.edit_actor", actor=owner.get_actor(), attributes=owner.export_actor_attributes())
|
ifc.run("owner.edit_actor", actor=owner.get_actor(), attributes=owner.export_actor_attributes())
|
||||||
disable_editing_actor(owner)
|
disable_editing_actor(owner)
|
||||||
|
|
||||||
|
|
||||||
def assign_actor(ifc: tool.Ifc, actor: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance) -> None:
|
def assign_actor(
|
||||||
|
ifc: type[tool.Ifc], actor: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance
|
||||||
|
) -> None:
|
||||||
ifc.run("owner.assign_actor", relating_actor=actor, related_object=element)
|
ifc.run("owner.assign_actor", relating_actor=actor, related_object=element)
|
||||||
|
|
||||||
|
|
||||||
def unassign_actor(ifc: tool.Ifc, actor: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance) -> None:
|
def unassign_actor(
|
||||||
|
ifc: type[tool.Ifc], actor: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance
|
||||||
|
) -> None:
|
||||||
ifc.run("owner.unassign_actor", relating_actor=actor, related_object=element)
|
ifc.run("owner.unassign_actor", relating_actor=actor, related_object=element)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class Blender(bonsai.core.tool.Blender):
|
|||||||
OBJECT_TYPES_THAT_SUPPORT_EDIT_GPENCIL_MODE = ("GPENCIL",)
|
OBJECT_TYPES_THAT_SUPPORT_EDIT_GPENCIL_MODE = ("GPENCIL",)
|
||||||
TYPE_MANAGER_ICON = "LIGHTPROBE_VOLUME"
|
TYPE_MANAGER_ICON = "LIGHTPROBE_VOLUME"
|
||||||
|
|
||||||
BLENDER_ENUM_ITEM = Union[tuple[str, str, str], tuple[str, str, str, str], tuple[str, str, str, str, str]]
|
BLENDER_ENUM_ITEM = Union[tuple[str, str, str], tuple[str, str, str, int], tuple[str, str, str, str, int]]
|
||||||
"""
|
"""
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
@@ -81,6 +81,7 @@ class Blender(bonsai.core.tool.Blender):
|
|||||||
|
|
||||||
- (identifier, name, description, icon, number)
|
- (identifier, name, description, icon, number)
|
||||||
"""
|
"""
|
||||||
|
BLENDER_ENUM_ITEMS = list[BLENDER_ENUM_ITEM]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def activate_camera(cls, obj: bpy.types.Object) -> None:
|
def activate_camera(cls, obj: bpy.types.Object) -> None:
|
||||||
|
|||||||
@@ -16,22 +16,33 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
import bpy
|
import bpy
|
||||||
import bonsai.bim.helper
|
import bonsai.bim.helper
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
from typing import Any, Union
|
from typing import Any, Union, TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bonsai.bim.prop import Attribute
|
||||||
|
from bonsai.bim.module.context.prop import BIMContextProperties
|
||||||
|
|
||||||
|
|
||||||
class Context(bonsai.core.tool.Context):
|
class Context(bonsai.core.tool.Context):
|
||||||
|
@classmethod
|
||||||
|
def get_context_props(cls) -> BIMContextProperties:
|
||||||
|
assert bpy.context.scene
|
||||||
|
return bpy.context.scene.BIMContextProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_context(cls, context: ifcopenshell.entity_instance) -> None:
|
def set_context(cls, context: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMContextProperties.active_context_id = context.id()
|
props = cls.get_context_props()
|
||||||
|
props.active_context_id = context.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_attributes(cls) -> None:
|
def import_attributes(cls) -> None:
|
||||||
props = bpy.context.scene.BIMContextProperties
|
props = cls.get_context_props()
|
||||||
props.context_attributes.clear()
|
props.context_attributes.clear()
|
||||||
context = cls.get_context()
|
context = cls.get_context()
|
||||||
|
|
||||||
@@ -52,20 +63,22 @@ class Context(bonsai.core.tool.Context):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_context(cls) -> None:
|
def clear_context(cls) -> None:
|
||||||
bpy.context.scene.BIMContextProperties.active_context_id = 0
|
props = cls.get_context_props()
|
||||||
|
props.active_context_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_context(cls) -> ifcopenshell.entity_instance:
|
def get_context(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMContextProperties.active_context_id)
|
props = cls.get_context_props()
|
||||||
|
return tool.Ifc.get().by_id(props.active_context_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_attributes(cls) -> dict[str, Any]:
|
def export_attributes(cls) -> dict[str, Any]:
|
||||||
def callback(attributes, blender_attribute) -> bool:
|
props = cls.get_context_props()
|
||||||
|
|
||||||
|
def callback(attributes: dict[str, Any], blender_attribute: Attribute) -> bool:
|
||||||
if blender_attribute.name == "Precision":
|
if blender_attribute.name == "Precision":
|
||||||
attributes["Precision"] = float(blender_attribute.get_value())
|
attributes["Precision"] = float(blender_attribute.get_value())
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return bonsai.bim.helper.export_attributes(
|
return bonsai.bim.helper.export_attributes(props.context_attributes, callback=callback)
|
||||||
bpy.context.scene.BIMContextProperties.context_attributes, callback=callback
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ if TYPE_CHECKING:
|
|||||||
BIMAnnotationProperties,
|
BIMAnnotationProperties,
|
||||||
BIMTextProperties,
|
BIMTextProperties,
|
||||||
BIMCameraProperties,
|
BIMCameraProperties,
|
||||||
|
BIMAssignedProductProperties,
|
||||||
)
|
)
|
||||||
from bonsai.bim.module.drawing.prop import Drawing as DrawingProperties
|
from bonsai.bim.module.drawing.prop import Drawing as DrawingProperties
|
||||||
|
|
||||||
@@ -105,15 +106,17 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_document_props(cls) -> DocProperties:
|
def get_document_props(cls) -> DocProperties:
|
||||||
return bpy.context.scene.DocProperties
|
assert (scene := bpy.context.scene)
|
||||||
|
return scene.DocProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_annotation_props(cls) -> BIMAnnotationProperties:
|
def get_annotation_props(cls) -> BIMAnnotationProperties:
|
||||||
return bpy.context.scene.BIMAnnotationProperties
|
assert (scene := bpy.context.scene)
|
||||||
|
return scene.BIMAnnotationProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_text_props(cls, obj: bpy.types.Object) -> BIMTextProperties:
|
def get_text_props(cls, obj: bpy.types.Object) -> BIMTextProperties:
|
||||||
return obj.BIMTextProperties
|
return obj.BIMTextProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_camera_props(cls, camera: Union[bpy.types.Object, bpy.types.Camera]) -> BIMCameraProperties:
|
def get_camera_props(cls, camera: Union[bpy.types.Object, bpy.types.Camera]) -> BIMCameraProperties:
|
||||||
@@ -124,7 +127,11 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
data = camera
|
data = camera
|
||||||
else:
|
else:
|
||||||
assert isinstance(data := camera.data, bpy.types.Camera)
|
assert isinstance(data := camera.data, bpy.types.Camera)
|
||||||
return data.BIMCameraProperties
|
return data.BIMCameraProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_object_assigned_product_props(cls, obj: bpy.types.Object) -> BIMAssignedProductProperties:
|
||||||
|
return obj.BIMAssignedProductProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def canonicalise_class_name(cls, name: str) -> str:
|
def canonicalise_class_name(cls, name: str) -> str:
|
||||||
@@ -406,7 +413,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def disable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
|
def disable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
|
||||||
obj.BIMAssignedProductProperties.is_editing_product = False
|
props = cls.get_object_assigned_product_props(obj)
|
||||||
|
props.is_editing_product = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def enable_editing(cls, obj: bpy.types.Object) -> None:
|
def enable_editing(cls, obj: bpy.types.Object) -> None:
|
||||||
@@ -447,7 +455,8 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def enable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
|
def enable_editing_assigned_product(cls, obj: bpy.types.Object) -> None:
|
||||||
obj.BIMAssignedProductProperties.is_editing_product = True
|
props = cls.get_object_assigned_product_props(obj)
|
||||||
|
props.is_editing_product = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def ensure_unique_drawing_name(cls, name: str) -> str:
|
def ensure_unique_drawing_name(cls, name: str) -> str:
|
||||||
@@ -1045,11 +1054,14 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def import_assigned_product(cls, obj: bpy.types.Object) -> None:
|
def import_assigned_product(cls, obj: bpy.types.Object) -> None:
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
assert element
|
||||||
product = cls.get_assigned_product(element)
|
product = cls.get_assigned_product(element)
|
||||||
|
props = cls.get_object_assigned_product_props(obj)
|
||||||
if product:
|
if product:
|
||||||
obj.BIMAssignedProductProperties.relating_product = tool.Ifc.get_object(product)
|
assert isinstance(product_obj := tool.Ifc.get_object(product), bpy.types.Object)
|
||||||
|
props.relating_product = product_obj
|
||||||
else:
|
else:
|
||||||
obj.BIMAssignedProductProperties.relating_product = None
|
props.relating_product = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def open_with_user_command(cls, user_command: str, path: str) -> None:
|
def open_with_user_command(cls, user_command: str, path: str) -> None:
|
||||||
|
|||||||
@@ -1030,7 +1030,7 @@ class Geometry(bonsai.core.tool.Geometry):
|
|||||||
return item.is_a("IfcSweptAreaSolid") or item.is_a("IfcHalfSpaceSolid")
|
return item.is_a("IfcSweptAreaSolid") or item.is_a("IfcHalfSpaceSolid")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_profile_based(cls, data: bpy.types.Mesh) -> bool:
|
def is_profile_based(cls, data: TYPES_WITH_MESH_PROPERTIES) -> bool:
|
||||||
props = tool.Geometry.get_mesh_props(data)
|
props = tool.Geometry.get_mesh_props(data)
|
||||||
return props.subshape_type == "PROFILE"
|
return props.subshape_type == "PROFILE"
|
||||||
|
|
||||||
|
|||||||
@@ -16,23 +16,35 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
import bpy
|
import bpy
|
||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import bonsai.bim.helper
|
import bonsai.bim.helper
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
from typing import Union, Any
|
from typing import Union, Any, TYPE_CHECKING, Literal
|
||||||
|
from typing_extensions import assert_never
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bonsai.bim.module.owner.prop import BIMOwnerProperties
|
||||||
|
|
||||||
|
|
||||||
class Owner(bonsai.core.tool.Owner):
|
class Owner(bonsai.core.tool.Owner):
|
||||||
|
@classmethod
|
||||||
|
def get_owner_props(cls) -> BIMOwnerProperties:
|
||||||
|
return bpy.context.scene.BIMOwnerProperties
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_user(cls, user: ifcopenshell.entity_instance) -> None:
|
def set_user(cls, user: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_user_id = user.id()
|
props = cls.get_owner_props()
|
||||||
|
props.active_user_id = user.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_user(cls) -> Union[ifcopenshell.entity_instance, None]:
|
def get_user(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
if bpy.context.scene.BIMOwnerProperties.active_user_id:
|
props = cls.get_owner_props()
|
||||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMOwnerProperties.active_user_id)
|
active_user_id = props.active_user_id
|
||||||
|
if active_user_id:
|
||||||
|
return tool.Ifc.get().by_id(active_user_id)
|
||||||
elif tool.Ifc.get_schema() == "IFC2X3":
|
elif tool.Ifc.get_schema() == "IFC2X3":
|
||||||
users = tool.Ifc.get().by_type("IfcPersonAndOrganization")
|
users = tool.Ifc.get().by_type("IfcPersonAndOrganization")
|
||||||
if users:
|
if users:
|
||||||
@@ -40,15 +52,17 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_user(cls) -> None:
|
def clear_user(cls) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_user_id = 0
|
props = cls.get_owner_props()
|
||||||
|
props.active_user_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_address(cls, address: ifcopenshell.entity_instance) -> None:
|
def set_address(cls, address: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_address_id = address.id()
|
props = cls.get_owner_props()
|
||||||
|
props.active_address_id = address.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_address_attributes(cls) -> None:
|
def import_address_attributes(cls) -> None:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = props = cls.get_owner_props()
|
||||||
props.address_attributes.clear()
|
props.address_attributes.clear()
|
||||||
props.address_lines.clear()
|
props.address_lines.clear()
|
||||||
props.telephone_numbers.clear()
|
props.telephone_numbers.clear()
|
||||||
@@ -58,7 +72,7 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
|
|
||||||
address = cls.get_address()
|
address = cls.get_address()
|
||||||
|
|
||||||
def callback(name, prop, data):
|
def callback(name: str, prop, data: dict[str, Any]) -> None:
|
||||||
if name == "AddressLines":
|
if name == "AddressLines":
|
||||||
for line in data[name] or []:
|
for line in data[name] or []:
|
||||||
props.address_lines.add().name = line
|
props.address_lines.add().name = line
|
||||||
@@ -79,15 +93,17 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_address(cls) -> None:
|
def clear_address(cls) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_address_id = 0
|
props = cls.get_owner_props()
|
||||||
|
props.active_address_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_address(cls) -> ifcopenshell.entity_instance:
|
def get_address(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_address_id)
|
props = cls.get_owner_props()
|
||||||
|
return tool.Ifc().get().by_id(props.active_address_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_address_attributes(cls) -> dict[str, Any]:
|
def export_address_attributes(cls) -> dict[str, Any]:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
attributes = bonsai.bim.helper.export_attributes(props.address_attributes)
|
attributes = bonsai.bim.helper.export_attributes(props.address_attributes)
|
||||||
if cls.get_address().is_a("IfcPostalAddress"):
|
if cls.get_address().is_a("IfcPostalAddress"):
|
||||||
attributes["AddressLines"] = [l.name for l in props.address_lines] or None
|
attributes["AddressLines"] = [l.name for l in props.address_lines] or None
|
||||||
@@ -98,9 +114,13 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
attributes["MessagingIDs"] = [l.name for l in props.messaging_ids] or None
|
attributes["MessagingIDs"] = [l.name for l in props.messaging_ids] or None
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
|
AddressAttributeType = Literal[
|
||||||
|
"AddressLines", "TelephoneNumbers", "FacsimileNumbers", "ElectronicMailAddresses", "MessagingIDs"
|
||||||
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_address_attribute(cls, name: str) -> None:
|
def add_address_attribute(cls, name: AddressAttributeType) -> None:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
if name == "AddressLines":
|
if name == "AddressLines":
|
||||||
props.address_lines.add()
|
props.address_lines.add()
|
||||||
elif name == "TelephoneNumbers":
|
elif name == "TelephoneNumbers":
|
||||||
@@ -111,10 +131,12 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
props.electronic_mail_addresses.add()
|
props.electronic_mail_addresses.add()
|
||||||
elif name == "MessagingIDs":
|
elif name == "MessagingIDs":
|
||||||
props.messaging_ids.add()
|
props.messaging_ids.add()
|
||||||
|
else:
|
||||||
|
assert_never(name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_address_attribute(cls, name: str, id: int) -> None:
|
def remove_address_attribute(cls, name: AddressAttributeType, id: int) -> None:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
if name == "AddressLines":
|
if name == "AddressLines":
|
||||||
props.address_lines.remove(id)
|
props.address_lines.remove(id)
|
||||||
elif name == "TelephoneNumbers":
|
elif name == "TelephoneNumbers":
|
||||||
@@ -125,47 +147,53 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
props.electronic_mail_addresses.remove(id)
|
props.electronic_mail_addresses.remove(id)
|
||||||
elif name == "MessagingIDs":
|
elif name == "MessagingIDs":
|
||||||
props.messaging_ids.remove(id)
|
props.messaging_ids.remove(id)
|
||||||
|
else:
|
||||||
|
assert_never(name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_organisation(cls, organisation: ifcopenshell.entity_instance) -> None:
|
def set_organisation(cls, organisation: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_organisation_id = organisation.id()
|
props = cls.get_owner_props()
|
||||||
|
props.active_organisation_id = organisation.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_organisation_attributes(cls) -> None:
|
def import_organisation_attributes(cls) -> None:
|
||||||
organisation = tool.Ifc.get().by_id(bpy.context.scene.BIMOwnerProperties.active_organisation_id)
|
props = cls.get_owner_props()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
organisation = tool.Ifc.get().by_id(props.active_organisation_id)
|
||||||
props.organisation_attributes.clear()
|
props.organisation_attributes.clear()
|
||||||
|
|
||||||
bonsai.bim.helper.import_attributes("IfcOrganization", props.organisation_attributes, organisation.get_info())
|
bonsai.bim.helper.import_attributes("IfcOrganization", props.organisation_attributes, organisation.get_info())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_organisation(cls) -> None:
|
def clear_organisation(cls) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_organisation_id = 0
|
props = cls.get_owner_props()
|
||||||
|
props.active_organisation_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_organisation_attributes(cls) -> dict[str, Any]:
|
def export_organisation_attributes(cls) -> dict[str, Any]:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
attributes = bonsai.bim.helper.export_attributes(props.organisation_attributes)
|
attributes = bonsai.bim.helper.export_attributes(props.organisation_attributes)
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_organisation(cls) -> ifcopenshell.entity_instance:
|
def get_organisation(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_organisation_id)
|
props = cls.get_owner_props()
|
||||||
|
return tool.Ifc().get().by_id(props.active_organisation_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_person(cls, person: ifcopenshell.entity_instance) -> None:
|
def set_person(cls, person: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_person_id = person.id()
|
props = cls.get_owner_props()
|
||||||
|
props.active_person_id = person.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_person_attributes(cls) -> None:
|
def import_person_attributes(cls) -> None:
|
||||||
person = tool.Ifc.get().by_id(bpy.context.scene.BIMOwnerProperties.active_person_id)
|
props = cls.get_owner_props()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
person = tool.Ifc.get().by_id(props.active_person_id)
|
||||||
props.person_attributes.clear()
|
props.person_attributes.clear()
|
||||||
props.middle_names.clear()
|
props.middle_names.clear()
|
||||||
props.prefix_titles.clear()
|
props.prefix_titles.clear()
|
||||||
props.suffix_titles.clear()
|
props.suffix_titles.clear()
|
||||||
|
|
||||||
def callback(name, prop, data):
|
def callback(name: str, prop, data: dict[str, Any]) -> None:
|
||||||
if name == "MiddleNames":
|
if name == "MiddleNames":
|
||||||
for name in data["MiddleNames"] or []:
|
for name in data["MiddleNames"] or []:
|
||||||
props.middle_names.add().name = name or ""
|
props.middle_names.add().name = name or ""
|
||||||
@@ -180,11 +208,12 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_person(cls) -> None:
|
def clear_person(cls) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_person_id = 0
|
props = cls.get_owner_props()
|
||||||
|
props.active_person_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_person_attributes(cls) -> dict[str, Any]:
|
def export_person_attributes(cls) -> dict[str, Any]:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
attributes = bonsai.bim.helper.export_attributes(props.person_attributes)
|
attributes = bonsai.bim.helper.export_attributes(props.person_attributes)
|
||||||
attributes["MiddleNames"] = [v.name for v in props.middle_names] if props.middle_names else None
|
attributes["MiddleNames"] = [v.name for v in props.middle_names] if props.middle_names else None
|
||||||
attributes["PrefixTitles"] = [v.name for v in props.prefix_titles] if props.prefix_titles else None
|
attributes["PrefixTitles"] = [v.name for v in props.prefix_titles] if props.prefix_titles else None
|
||||||
@@ -193,69 +222,85 @@ class Owner(bonsai.core.tool.Owner):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_person(cls) -> ifcopenshell.entity_instance:
|
def get_person(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_person_id)
|
props = cls.get_owner_props()
|
||||||
|
return tool.Ifc().get().by_id(props.active_person_id)
|
||||||
|
|
||||||
|
PersonAttributeType = Literal["MiddleNames", "PrefixTitles", "SuffixTitles"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_person_attribute(cls, name: str) -> None:
|
def add_person_attribute(cls, name: PersonAttributeType) -> None:
|
||||||
|
props = cls.get_owner_props()
|
||||||
if name == "MiddleNames":
|
if name == "MiddleNames":
|
||||||
bpy.context.scene.BIMOwnerProperties.middle_names.add()
|
props.middle_names.add()
|
||||||
elif name == "PrefixTitles":
|
elif name == "PrefixTitles":
|
||||||
bpy.context.scene.BIMOwnerProperties.prefix_titles.add()
|
props.prefix_titles.add()
|
||||||
elif name == "SuffixTitles":
|
elif name == "SuffixTitles":
|
||||||
bpy.context.scene.BIMOwnerProperties.suffix_titles.add()
|
props.suffix_titles.add()
|
||||||
|
else:
|
||||||
|
assert_never(name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_person_attribute(cls, name: str, id: int) -> None:
|
def remove_person_attribute(cls, name: PersonAttributeType, id: int) -> None:
|
||||||
|
props = cls.get_owner_props()
|
||||||
if name == "MiddleNames":
|
if name == "MiddleNames":
|
||||||
bpy.context.scene.BIMOwnerProperties.middle_names.remove(id)
|
props.middle_names.remove(id)
|
||||||
elif name == "PrefixTitles":
|
elif name == "PrefixTitles":
|
||||||
bpy.context.scene.BIMOwnerProperties.prefix_titles.remove(id)
|
props.prefix_titles.remove(id)
|
||||||
elif name == "SuffixTitles":
|
elif name == "SuffixTitles":
|
||||||
bpy.context.scene.BIMOwnerProperties.suffix_titles.remove(id)
|
props.suffix_titles.remove(id)
|
||||||
|
else:
|
||||||
|
assert_never(name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_role(cls, role: ifcopenshell.entity_instance) -> None:
|
def set_role(cls, role: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_role_id = role.id()
|
props = cls.get_owner_props()
|
||||||
|
props.active_role_id = role.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_role_attributes(cls) -> None:
|
def import_role_attributes(cls) -> None:
|
||||||
role = cls.get_role()
|
role = cls.get_role()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
props.role_attributes.clear()
|
props.role_attributes.clear()
|
||||||
bonsai.bim.helper.import_attributes("IfcActorRole", props.role_attributes, role.get_info())
|
bonsai.bim.helper.import_attributes("IfcActorRole", props.role_attributes, role.get_info())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_role(cls) -> None:
|
def clear_role(cls) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_role_id = 0
|
props = cls.get_owner_props()
|
||||||
|
props.active_role_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_role(cls) -> ifcopenshell.entity_instance:
|
def get_role(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_role_id)
|
props = cls.get_owner_props()
|
||||||
|
return tool.Ifc().get().by_id(props.active_role_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_role_attributes(cls) -> dict[str, Any]:
|
def export_role_attributes(cls) -> dict[str, Any]:
|
||||||
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMOwnerProperties.role_attributes)
|
props = cls.get_owner_props()
|
||||||
|
return bonsai.bim.helper.export_attributes(props.role_attributes)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_actor(cls, actor: ifcopenshell.entity_instance) -> None:
|
def set_actor(cls, actor: ifcopenshell.entity_instance) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_actor_id = actor.id()
|
props = cls.get_owner_props()
|
||||||
|
props.active_actor_id = actor.id()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_actor_attributes(cls, actor: ifcopenshell.entity_instance) -> None:
|
def import_actor_attributes(cls, actor: ifcopenshell.entity_instance) -> None:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
props.actor_attributes.clear()
|
props.actor_attributes.clear()
|
||||||
bonsai.bim.helper.import_attributes2(actor, props.actor_attributes)
|
bonsai.bim.helper.import_attributes2(actor, props.actor_attributes)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clear_actor(cls) -> None:
|
def clear_actor(cls) -> None:
|
||||||
bpy.context.scene.BIMOwnerProperties.active_actor_id = 0
|
props = cls.get_owner_props()
|
||||||
|
props.active_actor_id = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_actor_attributes(cls) -> dict[str, Any]:
|
def export_actor_attributes(cls) -> dict[str, Any]:
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = cls.get_owner_props()
|
||||||
attributes = bonsai.bim.helper.export_attributes(props.actor_attributes)
|
attributes = bonsai.bim.helper.export_attributes(props.actor_attributes)
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_actor(cls) -> ifcopenshell.entity_instance:
|
def get_actor(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc().get().by_id(bpy.context.scene.BIMOwnerProperties.active_actor_id)
|
props = cls.get_owner_props()
|
||||||
|
return tool.Ifc().get().by_id(props.active_actor_id)
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_task_attribute_value(cls, attribute_name: str) -> Any:
|
def get_task_attribute_value(cls, attribute_name: str) -> Any:
|
||||||
props = cls.get_work_schedule_props()
|
props = cls.get_work_schedule_props()
|
||||||
return props.task_attributes.get(attribute_name).get_value()
|
return props.task_attributes[attribute_name].get_value()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_active_task(cls) -> ifcopenshell.entity_instance:
|
def get_active_task(cls) -> ifcopenshell.entity_instance:
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ import bonsai.core.tool
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import pytest
|
import pytest
|
||||||
from test.bim.bootstrap import NewFile
|
from test.bim.bootstrap import NewFile
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
from bonsai.tool.blender import Blender as subject
|
from bonsai.tool.blender import Blender as subject
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
import bpy._typing.rna_enums as rna_enums
|
||||||
|
|
||||||
|
|
||||||
class TestImplementsTool(NewFile):
|
class TestImplementsTool(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
@@ -34,6 +38,7 @@ class TestCopyNodeGraph(NewFile):
|
|||||||
def test_run(self):
|
def test_run(self):
|
||||||
material_to = bpy.data.materials.new("material_to")
|
material_to = bpy.data.materials.new("material_to")
|
||||||
material_to.use_nodes = True
|
material_to.use_nodes = True
|
||||||
|
assert material_to.node_tree
|
||||||
material_to_nodes = material_to.node_tree.nodes
|
material_to_nodes = material_to.node_tree.nodes
|
||||||
assert len(material_to_nodes) == 2
|
assert len(material_to_nodes) == 2
|
||||||
for node in material_to_nodes:
|
for node in material_to_nodes:
|
||||||
@@ -70,7 +75,7 @@ class TestBlenderErrorMessageExtraction(NewFile):
|
|||||||
bl_idname = "object.test_fail_operator"
|
bl_idname = "object.test_fail_operator"
|
||||||
bl_label = "Test Fail Operator"
|
bl_label = "Test Fail Operator"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
|
||||||
self.report({"INFO"}, "Info message.")
|
self.report({"INFO"}, "Info message.")
|
||||||
subject.report_operator_errors(self, ERROR_REPORTS)
|
subject.report_operator_errors(self, ERROR_REPORTS)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ class TestAddBrickifcProject(NewFile):
|
|||||||
class TestAddBrickifcReference(NewFile):
|
class TestAddBrickifcReference(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
TestAddBrickifcProject().test_run()
|
TestAddBrickifcProject().test_run()
|
||||||
|
assert BrickStore.graph
|
||||||
element = tool.Ifc.get().createIfcChiller(ifcopenshell.guid.new())
|
element = tool.Ifc.get().createIfcChiller(ifcopenshell.guid.new())
|
||||||
element.Name = "Chiller"
|
element.Name = "Chiller"
|
||||||
project = URIRef(f"http://example.org/digitaltwin#{tool.Ifc.get().by_type('IfcProject')[0].GlobalId}")
|
project = URIRef(f"http://example.org/digitaltwin#{tool.Ifc.get().by_type('IfcProject')[0].GlobalId}")
|
||||||
@@ -173,6 +174,7 @@ class TestAddRelation(NewFile):
|
|||||||
class TestRemoveRelation(NewFile):
|
class TestRemoveRelation(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
TestAddRelation().test_run()
|
TestAddRelation().test_run()
|
||||||
|
assert BrickStore.graph
|
||||||
source, relation, destination = list(
|
source, relation, destination = list(
|
||||||
BrickStore.graph.triples((None, URIRef("https://brickschema.org/schema/Brick#feeds"), None))
|
BrickStore.graph.triples((None, URIRef("https://brickschema.org/schema/Brick#feeds"), None))
|
||||||
)[0]
|
)[0]
|
||||||
@@ -321,7 +323,7 @@ class TestGetConvertableBrickSystems(NewFile):
|
|||||||
|
|
||||||
|
|
||||||
class TestGetParentSpace(NewFile):
|
class TestGetParentSpace(NewFile):
|
||||||
def test_run(cls):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcBuildingStorey")
|
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcBuildingStorey")
|
||||||
subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace")
|
subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace")
|
||||||
@@ -333,17 +335,17 @@ class TestGetParentSpace(NewFile):
|
|||||||
|
|
||||||
|
|
||||||
class TestGetElementContainer(NewFile):
|
class TestGetElementContainer(NewFile):
|
||||||
def test_nothing(cls):
|
def test_nothing(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestGetElementSystems(NewFile):
|
class TestGetElementSystems(NewFile):
|
||||||
def test_nothing(cls):
|
def test_nothing(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestGetElementFeeds(NewFile):
|
class TestGetElementFeeds(NewFile):
|
||||||
def test_run(cls):
|
def test_run(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ import bpy
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.api.aggregate
|
import ifcopenshell.api.aggregate
|
||||||
|
import ifcopenshell.api.feature
|
||||||
|
import ifcopenshell.api.group
|
||||||
|
import ifcopenshell.api.spatial
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
@@ -34,6 +37,7 @@ class TestImplementsTool(NewFile):
|
|||||||
|
|
||||||
class TestAssign(NewIfc):
|
class TestAssign(NewIfc):
|
||||||
def test_walls_are_placed_in_its_spatial_collection(self):
|
def test_walls_are_placed_in_its_spatial_collection(self):
|
||||||
|
assert bpy.context.scene
|
||||||
wall_obj = bpy.data.objects.new("Object", None)
|
wall_obj = bpy.data.objects.new("Object", None)
|
||||||
wall_element = tool.Ifc.get().createIfcWall()
|
wall_element = tool.Ifc.get().createIfcWall()
|
||||||
tool.Ifc.link(wall_element, wall_obj)
|
tool.Ifc.link(wall_element, wall_obj)
|
||||||
@@ -48,6 +52,7 @@ class TestAssign(NewIfc):
|
|||||||
assert "IfcSite" in wall_obj.users_collection[0].name
|
assert "IfcSite" in wall_obj.users_collection[0].name
|
||||||
|
|
||||||
def test_walls_are_unsorted_if_not_decomposes(self):
|
def test_walls_are_unsorted_if_not_decomposes(self):
|
||||||
|
assert bpy.context.scene
|
||||||
wall_obj = bpy.data.objects.new("Object", None)
|
wall_obj = bpy.data.objects.new("Object", None)
|
||||||
wall_element = tool.Ifc.get().createIfcWall()
|
wall_element = tool.Ifc.get().createIfcWall()
|
||||||
tool.Ifc.link(wall_element, wall_obj)
|
tool.Ifc.link(wall_element, wall_obj)
|
||||||
@@ -57,6 +62,7 @@ class TestAssign(NewIfc):
|
|||||||
assert "Unsorted" in wall_obj.users_collection[0].name
|
assert "Unsorted" in wall_obj.users_collection[0].name
|
||||||
|
|
||||||
def test_spatial_structure_elements_are_placed_in_a_collection_of_the_same_name(self):
|
def test_spatial_structure_elements_are_placed_in_a_collection_of_the_same_name(self):
|
||||||
|
assert bpy.context.scene
|
||||||
building_obj = bpy.data.objects.new("IfcBuilding/Name", None)
|
building_obj = bpy.data.objects.new("IfcBuilding/Name", None)
|
||||||
building_element = tool.Ifc.get().createIfcBuilding()
|
building_element = tool.Ifc.get().createIfcBuilding()
|
||||||
tool.Ifc.link(building_element, building_obj)
|
tool.Ifc.link(building_element, building_obj)
|
||||||
@@ -71,6 +77,7 @@ class TestAssign(NewIfc):
|
|||||||
assert building_obj.users_collection[0].name == building_obj.name
|
assert building_obj.users_collection[0].name == building_obj.name
|
||||||
|
|
||||||
def test_spaces_are_special_and_are_placed_in_a_spaces_collection(self):
|
def test_spaces_are_special_and_are_placed_in_a_spaces_collection(self):
|
||||||
|
assert bpy.context.scene
|
||||||
space_obj = bpy.data.objects.new("IfcSpace/Name", None)
|
space_obj = bpy.data.objects.new("IfcSpace/Name", None)
|
||||||
space_element = tool.Ifc.get().createIfcSpace()
|
space_element = tool.Ifc.get().createIfcSpace()
|
||||||
tool.Ifc.link(space_element, space_obj)
|
tool.Ifc.link(space_element, space_obj)
|
||||||
@@ -85,6 +92,7 @@ class TestAssign(NewIfc):
|
|||||||
assert space_obj.users_collection[0].name == "IfcSpace"
|
assert space_obj.users_collection[0].name == "IfcSpace"
|
||||||
|
|
||||||
def test_multiple_assigns_do_not_create_duplicate_spatial_structure_collections(self):
|
def test_multiple_assigns_do_not_create_duplicate_spatial_structure_collections(self):
|
||||||
|
assert bpy.context.scene
|
||||||
space_obj = bpy.data.objects.new("IfcSpace/Name", None)
|
space_obj = bpy.data.objects.new("IfcSpace/Name", None)
|
||||||
space_element = tool.Ifc.get().createIfcSpace()
|
space_element = tool.Ifc.get().createIfcSpace()
|
||||||
tool.Ifc.link(space_element, space_obj)
|
tool.Ifc.link(space_element, space_obj)
|
||||||
@@ -102,6 +110,7 @@ class TestAssign(NewIfc):
|
|||||||
assert not bpy.data.collections.get("IfcSite/My Site.001")
|
assert not bpy.data.collections.get("IfcSite/My Site.001")
|
||||||
|
|
||||||
def test_spatial_zone_elements_are_not_placed_in_a_collection_of_the_same_name(self):
|
def test_spatial_zone_elements_are_not_placed_in_a_collection_of_the_same_name(self):
|
||||||
|
assert bpy.context.scene
|
||||||
space_obj = bpy.data.objects.new("IfcSpaceZone/Name", None)
|
space_obj = bpy.data.objects.new("IfcSpaceZone/Name", None)
|
||||||
space_element = tool.Ifc.get().createIfcSpatialZone()
|
space_element = tool.Ifc.get().createIfcSpatialZone()
|
||||||
tool.Ifc.link(space_element, space_obj)
|
tool.Ifc.link(space_element, space_obj)
|
||||||
@@ -116,6 +125,7 @@ class TestAssign(NewIfc):
|
|||||||
assert space_obj.users_collection[0].name != space_obj.name
|
assert space_obj.users_collection[0].name != space_obj.name
|
||||||
|
|
||||||
def test_aggregates_are_also_placed_in_their_container(self):
|
def test_aggregates_are_also_placed_in_their_container(self):
|
||||||
|
assert bpy.context.scene
|
||||||
element_obj = bpy.data.objects.new("IfcElementAssembly/Name", None)
|
element_obj = bpy.data.objects.new("IfcElementAssembly/Name", None)
|
||||||
element = tool.Ifc.get().createIfcElementAssembly()
|
element = tool.Ifc.get().createIfcElementAssembly()
|
||||||
subelement_obj = bpy.data.objects.new("IfcBeam/Name", None)
|
subelement_obj = bpy.data.objects.new("IfcBeam/Name", None)
|
||||||
@@ -142,6 +152,7 @@ class TestAssign(NewIfc):
|
|||||||
assert "IfcSite" in subelement_obj.users_collection[0].name
|
assert "IfcSite" in subelement_obj.users_collection[0].name
|
||||||
|
|
||||||
def test_projects_are_placed_in_a_collection_of_the_same_name(self):
|
def test_projects_are_placed_in_a_collection_of_the_same_name(self):
|
||||||
|
assert bpy.context.scene
|
||||||
tool.Ifc.set(ifcopenshell.file())
|
tool.Ifc.set(ifcopenshell.file())
|
||||||
element_obj = bpy.data.objects.new("IfcProject/Name", None)
|
element_obj = bpy.data.objects.new("IfcProject/Name", None)
|
||||||
element = tool.Ifc.get().createIfcProject()
|
element = tool.Ifc.get().createIfcProject()
|
||||||
@@ -152,6 +163,7 @@ class TestAssign(NewIfc):
|
|||||||
assert element_obj.users_collection[0].name == element_obj.name
|
assert element_obj.users_collection[0].name == element_obj.name
|
||||||
|
|
||||||
def test_multiple_assigns_do_not_create_duplicate_collections(self):
|
def test_multiple_assigns_do_not_create_duplicate_collections(self):
|
||||||
|
assert bpy.context.scene
|
||||||
tool.Ifc.set(ifcopenshell.file())
|
tool.Ifc.set(ifcopenshell.file())
|
||||||
element_obj = bpy.data.objects.new("IfcProject/Name", None)
|
element_obj = bpy.data.objects.new("IfcProject/Name", None)
|
||||||
element = tool.Ifc.get().createIfcProject()
|
element = tool.Ifc.get().createIfcProject()
|
||||||
@@ -163,6 +175,7 @@ class TestAssign(NewIfc):
|
|||||||
assert not bpy.data.collections.get("IfcProject/Name.001")
|
assert not bpy.data.collections.get("IfcProject/Name.001")
|
||||||
|
|
||||||
def test_own_collections_are_retained_and_name_synced(self):
|
def test_own_collections_are_retained_and_name_synced(self):
|
||||||
|
assert bpy.context.scene
|
||||||
building_obj = bpy.data.objects.new("IfcBuilding/Name", None)
|
building_obj = bpy.data.objects.new("IfcBuilding/Name", None)
|
||||||
building_element = tool.Ifc.get().createIfcBuilding()
|
building_element = tool.Ifc.get().createIfcBuilding()
|
||||||
tool.Ifc.link(building_element, building_obj)
|
tool.Ifc.link(building_element, building_obj)
|
||||||
@@ -178,22 +191,24 @@ class TestAssign(NewIfc):
|
|||||||
)
|
)
|
||||||
subject.assign(building_obj)
|
subject.assign(building_obj)
|
||||||
assert bpy.context.scene.collection.children.find(building_collection.name) != -1
|
assert bpy.context.scene.collection.children.find(building_collection.name) != -1
|
||||||
assert bpy.data.collections.get("IfcSite/My Site").children.find(building_collection.name) == -1
|
assert bpy.data.collections["IfcSite/My Site"].children.find(building_collection.name) == -1
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.find(building_collection.name) == -1
|
assert bpy.data.collections["IfcProject/My Project"].children.find(building_collection.name) == -1
|
||||||
assert bpy.context.scene.collection.children.find(building_collection.name) != -1
|
assert bpy.context.scene.collection.children.find(building_collection.name) != -1
|
||||||
assert building_collection.objects.find(building_obj.name) != -1
|
assert building_collection.objects.find(building_obj.name) != -1
|
||||||
assert building_collection.name == "IfcBuilding/Name"
|
assert building_collection.name == "IfcBuilding/Name"
|
||||||
|
|
||||||
def test_types_are_placed_in_the_types_collection(self):
|
def test_types_are_placed_in_the_types_collection(self):
|
||||||
|
assert bpy.context.scene
|
||||||
element_obj = bpy.data.objects.new("IfcWallType/Name", None)
|
element_obj = bpy.data.objects.new("IfcWallType/Name", None)
|
||||||
element = tool.Ifc.get().createIfcWallType()
|
element = tool.Ifc.get().createIfcWallType()
|
||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
bpy.context.scene.collection.objects.link(element_obj)
|
bpy.context.scene.collection.objects.link(element_obj)
|
||||||
subject.assign(element_obj)
|
subject.assign(element_obj)
|
||||||
assert element_obj.users_collection[0].name == "IfcTypeProduct"
|
assert element_obj.users_collection[0].name == "IfcTypeProduct"
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.get("IfcTypeProduct")
|
assert bpy.data.collections["IfcProject/My Project"].children.get("IfcTypeProduct")
|
||||||
|
|
||||||
def test_openings_are_placed_in_their_voided_elements_container(self):
|
def test_openings_are_placed_in_their_voided_elements_container(self):
|
||||||
|
assert bpy.context.scene
|
||||||
element_obj = bpy.data.objects.new("IfcOpeningElement/Name", None)
|
element_obj = bpy.data.objects.new("IfcOpeningElement/Name", None)
|
||||||
element = tool.Ifc.get().createIfcOpeningElement()
|
element = tool.Ifc.get().createIfcOpeningElement()
|
||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
@@ -210,6 +225,7 @@ class TestAssign(NewIfc):
|
|||||||
assert element_obj.users_collection[0].name == "IfcSite/My Site"
|
assert element_obj.users_collection[0].name == "IfcSite/My Site"
|
||||||
|
|
||||||
def test_grids_are_placed_in_their_container(self):
|
def test_grids_are_placed_in_their_container(self):
|
||||||
|
assert bpy.context.scene
|
||||||
element_obj = bpy.data.objects.new("IfcGrid/Name", None)
|
element_obj = bpy.data.objects.new("IfcGrid/Name", None)
|
||||||
element = tool.Ifc.get().createIfcGrid()
|
element = tool.Ifc.get().createIfcGrid()
|
||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
@@ -223,6 +239,7 @@ class TestAssign(NewIfc):
|
|||||||
assert element_obj.users_collection[0].name == "IfcSite/My Site"
|
assert element_obj.users_collection[0].name == "IfcSite/My Site"
|
||||||
|
|
||||||
def test_grids_axes_are_placed_in_the_grids_container(self):
|
def test_grids_axes_are_placed_in_the_grids_container(self):
|
||||||
|
assert bpy.context.scene
|
||||||
element_obj = bpy.data.objects.new("IfcGrid/Name", None)
|
element_obj = bpy.data.objects.new("IfcGrid/Name", None)
|
||||||
axis_obj = bpy.data.objects.new("IfcGrid/Name", None)
|
axis_obj = bpy.data.objects.new("IfcGrid/Name", None)
|
||||||
axis = tool.Ifc.get().createIfcGridAxis()
|
axis = tool.Ifc.get().createIfcGridAxis()
|
||||||
@@ -250,7 +267,7 @@ class TestAssign(NewIfc):
|
|||||||
|
|
||||||
subject.assign(element_obj)
|
subject.assign(element_obj)
|
||||||
assert element_obj.users_collection[0].name == "IfcAnnotation/DRAWING"
|
assert element_obj.users_collection[0].name == "IfcAnnotation/DRAWING"
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.get("IfcAnnotation/DRAWING")
|
assert bpy.data.collections["IfcProject/My Project"].children.get("IfcAnnotation/DRAWING")
|
||||||
|
|
||||||
def test_annotations_are_placed_in_their_drawings_collection(self):
|
def test_annotations_are_placed_in_their_drawings_collection(self):
|
||||||
self.test_drawings_are_placed_in_their_own_collection()
|
self.test_drawings_are_placed_in_their_own_collection()
|
||||||
@@ -272,7 +289,7 @@ class TestAssign(NewIfc):
|
|||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
subject.assign(element_obj)
|
subject.assign(element_obj)
|
||||||
assert element_obj.users_collection[0].name == "IfcStructuralItem"
|
assert element_obj.users_collection[0].name == "IfcStructuralItem"
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.get("IfcStructuralItem")
|
assert bpy.data.collections["IfcProject/My Project"].children.get("IfcStructuralItem")
|
||||||
|
|
||||||
def test_structural_connections_are_placed_in_a_connections_collection(self):
|
def test_structural_connections_are_placed_in_a_connections_collection(self):
|
||||||
element_obj = bpy.data.objects.new("IfcStructuralCurveConnection/Name", None)
|
element_obj = bpy.data.objects.new("IfcStructuralCurveConnection/Name", None)
|
||||||
@@ -280,7 +297,7 @@ class TestAssign(NewIfc):
|
|||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
subject.assign(element_obj)
|
subject.assign(element_obj)
|
||||||
assert element_obj.users_collection[0].name == "IfcStructuralItem"
|
assert element_obj.users_collection[0].name == "IfcStructuralItem"
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.get("IfcStructuralItem")
|
assert bpy.data.collections["IfcProject/My Project"].children.get("IfcStructuralItem")
|
||||||
|
|
||||||
|
|
||||||
class TestAssignIFC4X3(NewIfc4X3):
|
class TestAssignIFC4X3(NewIfc4X3):
|
||||||
@@ -290,7 +307,7 @@ class TestAssignIFC4X3(NewIfc4X3):
|
|||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
subject.assign(element_obj)
|
subject.assign(element_obj)
|
||||||
assert element_obj.users_collection[0].name == "IfcLinearPositioningElement"
|
assert element_obj.users_collection[0].name == "IfcLinearPositioningElement"
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.get("IfcLinearPositioningElement")
|
assert bpy.data.collections["IfcProject/My Project"].children.get("IfcLinearPositioningElement")
|
||||||
|
|
||||||
def test_referents_are_placed_in_a_special_collection(self):
|
def test_referents_are_placed_in_a_special_collection(self):
|
||||||
element_obj = bpy.data.objects.new("Name", None)
|
element_obj = bpy.data.objects.new("Name", None)
|
||||||
@@ -298,4 +315,4 @@ class TestAssignIFC4X3(NewIfc4X3):
|
|||||||
tool.Ifc.link(element, element_obj)
|
tool.Ifc.link(element, element_obj)
|
||||||
subject.assign(element_obj)
|
subject.assign(element_obj)
|
||||||
assert element_obj.users_collection[0].name == "IfcReferent"
|
assert element_obj.users_collection[0].name == "IfcReferent"
|
||||||
assert bpy.data.collections.get("IfcProject/My Project").children.get("IfcReferent")
|
assert bpy.data.collections["IfcProject/My Project"].children.get("IfcReferent")
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ class TestSetContext(test.bim.bootstrap.NewFile):
|
|||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
context = ifc.createIfcGeometricRepresentationContext()
|
context = ifc.createIfcGeometricRepresentationContext()
|
||||||
subject.set_context(context)
|
subject.set_context(context)
|
||||||
assert bpy.context.scene.BIMContextProperties.active_context_id == context.id()
|
props = subject.get_context_props()
|
||||||
|
assert props.active_context_id == context.id()
|
||||||
|
|
||||||
|
|
||||||
class TestImportAttributes(test.bim.bootstrap.NewFile):
|
class TestImportAttributes(test.bim.bootstrap.NewFile):
|
||||||
@@ -48,11 +49,11 @@ class TestImportAttributes(test.bim.bootstrap.NewFile):
|
|||||||
context.Precision = 1
|
context.Precision = 1
|
||||||
subject.set_context(context)
|
subject.set_context(context)
|
||||||
subject.import_attributes()
|
subject.import_attributes()
|
||||||
props = bpy.context.scene.BIMContextProperties
|
props = subject.get_context_props()
|
||||||
assert props.context_attributes.get("ContextIdentifier").string_value == "ContextIdentifier"
|
assert props.context_attributes["ContextIdentifier"].string_value == "ContextIdentifier"
|
||||||
assert props.context_attributes.get("ContextType").string_value == "ContextType"
|
assert props.context_attributes["ContextType"].string_value == "ContextType"
|
||||||
assert props.context_attributes.get("CoordinateSpaceDimension").int_value == 1
|
assert props.context_attributes["CoordinateSpaceDimension"].int_value == 1
|
||||||
assert props.context_attributes.get("Precision").string_value == "1.0"
|
assert props.context_attributes["Precision"].string_value == "1.0"
|
||||||
|
|
||||||
def test_importing_a_subcontext(self):
|
def test_importing_a_subcontext(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -63,11 +64,11 @@ class TestImportAttributes(test.bim.bootstrap.NewFile):
|
|||||||
subcontext.UserDefinedTargetView = "UserDefinedTargetView"
|
subcontext.UserDefinedTargetView = "UserDefinedTargetView"
|
||||||
subject.set_context(subcontext)
|
subject.set_context(subcontext)
|
||||||
subject.import_attributes()
|
subject.import_attributes()
|
||||||
props = bpy.context.scene.BIMContextProperties
|
props = subject.get_context_props()
|
||||||
assert props.context_attributes.get("TargetScale").float_value == 0.5
|
assert props.context_attributes["TargetScale"].float_value == 0.5
|
||||||
assert props.context_attributes.get("TargetView").enum_value == "NOTDEFINED"
|
assert props.context_attributes["TargetView"].enum_value == "NOTDEFINED"
|
||||||
assert props.context_attributes.get("UserDefinedTargetView").string_value == "UserDefinedTargetView"
|
assert props.context_attributes["UserDefinedTargetView"].string_value == "UserDefinedTargetView"
|
||||||
assert not props.context_attributes.get("Precision")
|
assert not props.context_attributes["Precision"]
|
||||||
|
|
||||||
def test_importing_twice(self):
|
def test_importing_twice(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -78,15 +79,16 @@ class TestImportAttributes(test.bim.bootstrap.NewFile):
|
|||||||
subject.import_attributes()
|
subject.import_attributes()
|
||||||
context.ContextIdentifier = "ContextIdentifier2"
|
context.ContextIdentifier = "ContextIdentifier2"
|
||||||
subject.import_attributes()
|
subject.import_attributes()
|
||||||
props = bpy.context.scene.BIMContextProperties
|
props = subject.get_context_props()
|
||||||
assert props.context_attributes.get("ContextIdentifier").string_value == "ContextIdentifier2"
|
assert props.context_attributes["ContextIdentifier"].string_value == "ContextIdentifier2"
|
||||||
|
|
||||||
|
|
||||||
class TestClearContext(test.bim.bootstrap.NewFile):
|
class TestClearContext(test.bim.bootstrap.NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
TestSetContext().test_run()
|
TestSetContext().test_run()
|
||||||
subject.clear_context()
|
subject.clear_context()
|
||||||
assert bpy.context.scene.BIMContextProperties.active_context_id == 0
|
props = subject.get_context_props()
|
||||||
|
assert props.active_context_id == 0
|
||||||
|
|
||||||
|
|
||||||
class TestGetContext(test.bim.bootstrap.NewFile):
|
class TestGetContext(test.bim.bootstrap.NewFile):
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from pathlib import Path
|
|||||||
import bpy
|
import bpy
|
||||||
import mathutils
|
import mathutils
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api.root
|
||||||
import ifcopenshell.guid
|
import ifcopenshell.guid
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
@@ -68,7 +69,7 @@ class TestCreateCamera(NewFile):
|
|||||||
class TestCreateSvgSheet(NewFile):
|
class TestCreateSvgSheet(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
|
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
ifc_path = Path("test/files/temp/test.ifc").absolute()
|
ifc_path = Path("test/files/temp/test.ifc").absolute()
|
||||||
bpy.ops.bim.save_project(filepath=str(ifc_path), should_save_as=True)
|
bpy.ops.bim.save_project(filepath=str(ifc_path), should_save_as=True)
|
||||||
@@ -92,6 +93,7 @@ class TestDeleteCollection(NewFile):
|
|||||||
|
|
||||||
class TestDeleteDrawingElements(NewFile):
|
class TestDeleteDrawingElements(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
|
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
|
||||||
@@ -155,13 +157,15 @@ class TestDisableEditingText(NewFile):
|
|||||||
class TestDisableEditingAssignedProduct(NewFile):
|
class TestDisableEditingAssignedProduct(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
obj.BIMAssignedProductProperties.is_editing_product = True
|
props = subject.get_object_assigned_product_props(obj)
|
||||||
|
props.is_editing_product = True
|
||||||
subject.disable_editing_assigned_product(obj)
|
subject.disable_editing_assigned_product(obj)
|
||||||
assert obj.BIMAssignedProductProperties.is_editing_product == False
|
assert props.is_editing_product == False
|
||||||
|
|
||||||
|
|
||||||
class TestEnableEditing(NewFile):
|
class TestEnableEditing(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
bpy.context.scene.collection.objects.link(obj)
|
bpy.context.scene.collection.objects.link(obj)
|
||||||
subject.enable_editing(obj)
|
subject.enable_editing(obj)
|
||||||
@@ -211,8 +215,9 @@ class TestEnableEditingText(NewFile):
|
|||||||
class TestEnableEditingAssignedProduct(NewFile):
|
class TestEnableEditingAssignedProduct(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
|
props = subject.get_object_assigned_product_props(obj)
|
||||||
subject.enable_editing_assigned_product(obj)
|
subject.enable_editing_assigned_product(obj)
|
||||||
assert obj.BIMAssignedProductProperties.is_editing_product == True
|
assert props.is_editing_product == True
|
||||||
|
|
||||||
|
|
||||||
class TestEnsureUniqueDrawingName(NewFile):
|
class TestEnsureUniqueDrawingName(NewFile):
|
||||||
@@ -314,6 +319,7 @@ class TestGetDocumentUri(NewFile):
|
|||||||
|
|
||||||
class TestGetDrawingCollection(NewFile):
|
class TestGetDrawingCollection(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
@@ -378,6 +384,7 @@ class TestGenerateDrawingMatrix(NewFile):
|
|||||||
assert subject.generate_drawing_matrix("PLAN_VIEW", 0) == mathutils.Matrix()
|
assert subject.generate_drawing_matrix("PLAN_VIEW", 0) == mathutils.Matrix()
|
||||||
|
|
||||||
def test_creating_a_plan_view_at_the_cursor_at_a_storey(self):
|
def test_creating_a_plan_view_at_the_cursor_at_a_storey(self):
|
||||||
|
assert bpy.context.scene
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
@@ -397,6 +404,7 @@ class TestGenerateDrawingMatrix(NewFile):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_an_rcp_at_the_cursor_at_a_storey(self):
|
def test_creating_an_rcp_at_the_cursor_at_a_storey(self):
|
||||||
|
assert bpy.context.scene
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
@@ -410,48 +418,56 @@ class TestGenerateDrawingMatrix(NewFile):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_a_north_elevation_at_the_cursor(self):
|
def test_creating_a_north_elevation_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "NORTH") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "NORTH") == mathutils.Matrix(
|
||||||
((-1, 0, 0, 1), (0, 0, 1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((-1, 0, 0, 1), (0, 0, 1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_a_south_elevation_at_the_cursor(self):
|
def test_creating_a_south_elevation_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "SOUTH") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "SOUTH") == mathutils.Matrix(
|
||||||
((1, 0, 0, 1), (0, 0, -1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((1, 0, 0, 1), (0, 0, -1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_an_east_elevation_at_the_cursor(self):
|
def test_creating_an_east_elevation_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "EAST") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "EAST") == mathutils.Matrix(
|
||||||
((0, 0, 1, 1), (1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((0, 0, 1, 1), (1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_a_west_elevation_at_the_cursor(self):
|
def test_creating_a_west_elevation_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "WEST") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("ELEVATION_VIEW", "WEST") == mathutils.Matrix(
|
||||||
((0, 0, -1, 1), (-1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((0, 0, -1, 1), (-1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_a_north_section_at_the_cursor(self):
|
def test_creating_a_north_section_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("SECTION_VIEW", "NORTH") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("SECTION_VIEW", "NORTH") == mathutils.Matrix(
|
||||||
((1, 0, 0, 1), (0, 0, -1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((1, 0, 0, 1), (0, 0, -1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_a_south_section_at_the_cursor(self):
|
def test_creating_a_south_section_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("SECTION_VIEW", "SOUTH") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("SECTION_VIEW", "SOUTH") == mathutils.Matrix(
|
||||||
((-1, 0, 0, 1), (0, 0, 1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((-1, 0, 0, 1), (0, 0, 1, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_an_east_section_at_the_cursor(self):
|
def test_creating_an_east_section_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("SECTION_VIEW", "EAST") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("SECTION_VIEW", "EAST") == mathutils.Matrix(
|
||||||
((0, 0, -1, 1), (-1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((0, 0, -1, 1), (-1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_creating_a_west_section_at_the_cursor(self):
|
def test_creating_a_west_section_at_the_cursor(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.generate_drawing_matrix("SECTION_VIEW", "WEST") == mathutils.Matrix(
|
assert subject.generate_drawing_matrix("SECTION_VIEW", "WEST") == mathutils.Matrix(
|
||||||
((0, 0, 1, 1), (1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
((0, 0, 1, 1), (1, 0, 0, 2), (0, 1, 0, 3), (0, 0, 0, 1))
|
||||||
@@ -598,9 +614,9 @@ class TestImportTextAttributes(NewFile):
|
|||||||
subject.import_text_attributes(obj)
|
subject.import_text_attributes(obj)
|
||||||
props = tool.Drawing.get_text_props(obj)
|
props = tool.Drawing.get_text_props(obj)
|
||||||
literal_props = props.literals[0]
|
literal_props = props.literals[0]
|
||||||
assert literal_props.attributes.get("Literal").string_value == "Literal"
|
assert literal_props.attributes["Literal"].string_value == "Literal"
|
||||||
assert literal_props.attributes.get("Path").enum_value == "RIGHT"
|
assert literal_props.attributes["Path"].enum_value == "RIGHT"
|
||||||
assert literal_props.attributes.get("BoxAlignment").string_value == "bottom-left"
|
assert literal_props.attributes["BoxAlignment"].string_value == "bottom-left"
|
||||||
|
|
||||||
|
|
||||||
class TestImportAssignedProduct(NewFile):
|
class TestImportAssignedProduct(NewFile):
|
||||||
@@ -615,7 +631,8 @@ class TestImportAssignedProduct(NewFile):
|
|||||||
tool.Ifc.link(wall, wall_obj)
|
tool.Ifc.link(wall, wall_obj)
|
||||||
tool.Ifc.link(label, label_obj)
|
tool.Ifc.link(label, label_obj)
|
||||||
subject.import_assigned_product(label_obj)
|
subject.import_assigned_product(label_obj)
|
||||||
assert label_obj.BIMAssignedProductProperties.relating_product == wall_obj
|
props = subject.get_object_assigned_product_props(label_obj)
|
||||||
|
assert props.relating_product == wall_obj
|
||||||
|
|
||||||
def test_doing_nothing_if_no_product_to_import(self):
|
def test_doing_nothing_if_no_product_to_import(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -624,7 +641,8 @@ class TestImportAssignedProduct(NewFile):
|
|||||||
label_obj = bpy.data.objects.new("Object", None)
|
label_obj = bpy.data.objects.new("Object", None)
|
||||||
tool.Ifc.link(label, label_obj)
|
tool.Ifc.link(label, label_obj)
|
||||||
subject.import_assigned_product(label_obj)
|
subject.import_assigned_product(label_obj)
|
||||||
assert label_obj.BIMAssignedProductProperties.relating_product is None
|
props = subject.get_object_assigned_product_props(label_obj)
|
||||||
|
assert props.relating_product is None
|
||||||
|
|
||||||
|
|
||||||
class TestOpenSchedule(NewFile):
|
class TestOpenSchedule(NewFile):
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ class TestImportProjectedCRS(NewFile):
|
|||||||
projected_crs.MapUnit = unit
|
projected_crs.MapUnit = unit
|
||||||
subject.import_projected_crs()
|
subject.import_projected_crs()
|
||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
assert props.projected_crs.get("Name").string_value == "Name"
|
assert props.projected_crs["Name"].string_value == "Name"
|
||||||
assert props.projected_crs.get("Description").string_value == "Description"
|
assert props.projected_crs["Description"].string_value == "Description"
|
||||||
assert props.projected_crs.get("GeodeticDatum").string_value == "GeodeticDatum"
|
assert props.projected_crs["GeodeticDatum"].string_value == "GeodeticDatum"
|
||||||
assert props.projected_crs.get("VerticalDatum").string_value == "VerticalDatum"
|
assert props.projected_crs["VerticalDatum"].string_value == "VerticalDatum"
|
||||||
assert props.projected_crs.get("MapProjection").string_value == "MapProjection"
|
assert props.projected_crs["MapProjection"].string_value == "MapProjection"
|
||||||
assert props.projected_crs.get("MapZone").string_value == "MapZone"
|
assert props.projected_crs["MapZone"].string_value == "MapZone"
|
||||||
assert props.projected_crs.get("MapUnit").enum_value == str(unit.id())
|
assert props.projected_crs["MapUnit"].enum_value == str(unit.id())
|
||||||
|
|
||||||
def test_run_ifc2x3(self):
|
def test_run_ifc2x3(self):
|
||||||
ifc = ifcopenshell.file(schema="IFC2X3")
|
ifc = ifcopenshell.file(schema="IFC2X3")
|
||||||
@@ -100,13 +100,13 @@ class TestImportCoordinateOperation(NewFile):
|
|||||||
map_conversion.Scale = 6
|
map_conversion.Scale = 6
|
||||||
subject.import_coordinate_operation()
|
subject.import_coordinate_operation()
|
||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
assert props.coordinate_operation.get("Eastings").string_value == "1.0"
|
assert props.coordinate_operation["Eastings"].string_value == "1.0"
|
||||||
assert props.coordinate_operation.get("Northings").string_value == "2.0"
|
assert props.coordinate_operation["Northings"].string_value == "2.0"
|
||||||
assert props.coordinate_operation.get("OrthogonalHeight").string_value == "3.0"
|
assert props.coordinate_operation["OrthogonalHeight"].string_value == "3.0"
|
||||||
assert props.x_axis_abscissa == "4.0"
|
assert props.x_axis_abscissa == "4.0"
|
||||||
assert props.x_axis_ordinate == "5.0"
|
assert props.x_axis_ordinate == "5.0"
|
||||||
assert props.grid_north_angle == "-51.3401917"
|
assert props.grid_north_angle == "-51.3401917"
|
||||||
assert props.coordinate_operation.get("Scale").string_value == "6.0"
|
assert props.coordinate_operation["Scale"].string_value == "6.0"
|
||||||
|
|
||||||
def test_run_ifc2x3(self):
|
def test_run_ifc2x3(self):
|
||||||
ifc = ifcopenshell.file(schema="IFC2X3")
|
ifc = ifcopenshell.file(schema="IFC2X3")
|
||||||
@@ -220,6 +220,7 @@ class TestGetCursorLocation(NewFile):
|
|||||||
ifcopenshell.api.run("context.add_context", ifc, context_type="Model")
|
ifcopenshell.api.run("context.add_context", ifc, context_type="Model")
|
||||||
unit = ifcopenshell.api.run("unit.add_si_unit", ifc, unit_type="LENGTHUNIT", prefix="MILLI")
|
unit = ifcopenshell.api.run("unit.add_si_unit", ifc, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||||
ifcopenshell.api.run("unit.assign_unit", ifc, units=[unit])
|
ifcopenshell.api.run("unit.assign_unit", ifc, units=[unit])
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
bpy.context.scene.cursor.location = (1.0, 2.0, 3.0)
|
||||||
assert subject.get_cursor_location() == [1000.0, 2000.0, 3000.0]
|
assert subject.get_cursor_location() == [1000.0, 2000.0, 3000.0]
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ class TestXyz2Enh(NewFile):
|
|||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
|
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
assert subject.xyz2enh([0.0, 0.0, 0.0]) == (0.0, 0.0, 0.0)
|
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (0.0, 0.0, 0.0)
|
||||||
|
|
||||||
def test_using_the_blender_offset(self):
|
def test_using_the_blender_offset(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -238,7 +239,7 @@ class TestXyz2Enh(NewFile):
|
|||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
props.has_blender_offset = True
|
props.has_blender_offset = True
|
||||||
props.blender_offset_x = "1.0"
|
props.blender_offset_x = "1.0"
|
||||||
assert subject.xyz2enh([0.0, 0.0, 0.0]) == (1.0, 0.0, 0.0)
|
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (1.0, 0.0, 0.0)
|
||||||
|
|
||||||
def test_using_the_map_conversion(self):
|
def test_using_the_map_conversion(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -248,7 +249,7 @@ class TestXyz2Enh(NewFile):
|
|||||||
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
||||||
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
||||||
map_conversion.Eastings = 1.0
|
map_conversion.Eastings = 1.0
|
||||||
assert subject.xyz2enh([0.0, 0.0, 0.0]) == (1.0, 0.0, 0.0)
|
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (1.0, 0.0, 0.0)
|
||||||
|
|
||||||
def test_applying_both_blender_offset_and_map_conversion(self):
|
def test_applying_both_blender_offset_and_map_conversion(self):
|
||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
@@ -261,7 +262,7 @@ class TestXyz2Enh(NewFile):
|
|||||||
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
||||||
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
||||||
map_conversion.Northings = 1.0
|
map_conversion.Northings = 1.0
|
||||||
assert subject.xyz2enh([0.0, 0.0, 0.0]) == (1.0, 1.0, 0.0)
|
assert subject.xyz2enh((0.0, 0.0, 0.0)) == (1.0, 1.0, 0.0)
|
||||||
|
|
||||||
|
|
||||||
class TestEnh2Xyz(NewFile):
|
class TestEnh2Xyz(NewFile):
|
||||||
@@ -269,7 +270,7 @@ class TestEnh2Xyz(NewFile):
|
|||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
|
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
assert subject.enh2xyz([0.0, 0.0, 0.0]) == (0.0, 0.0, 0.0)
|
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (0.0, 0.0, 0.0)
|
||||||
|
|
||||||
def test_using_the_blender_offset(self):
|
def test_using_the_blender_offset(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -278,7 +279,7 @@ class TestEnh2Xyz(NewFile):
|
|||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
props.has_blender_offset = True
|
props.has_blender_offset = True
|
||||||
props.blender_offset_x = "1.0"
|
props.blender_offset_x = "1.0"
|
||||||
assert subject.enh2xyz([0.0, 0.0, 0.0]) == (-1.0, 0.0, 0.0)
|
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (-1.0, 0.0, 0.0)
|
||||||
|
|
||||||
def test_using_the_map_conversion(self):
|
def test_using_the_map_conversion(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -288,7 +289,7 @@ class TestEnh2Xyz(NewFile):
|
|||||||
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
||||||
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
||||||
map_conversion.Eastings = 1.0
|
map_conversion.Eastings = 1.0
|
||||||
assert subject.enh2xyz([0.0, 0.0, 0.0]) == (-1.0, 0.0, 0.0)
|
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (-1.0, 0.0, 0.0)
|
||||||
|
|
||||||
def test_applying_both_blender_offset_and_map_conversion(self):
|
def test_applying_both_blender_offset_and_map_conversion(self):
|
||||||
props = tool.Georeference.get_georeference_props()
|
props = tool.Georeference.get_georeference_props()
|
||||||
@@ -301,4 +302,4 @@ class TestEnh2Xyz(NewFile):
|
|||||||
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
ifcopenshell.api.run("georeference.add_georeferencing", ifc)
|
||||||
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
map_conversion = ifc.by_type("IfcMapConversion")[0]
|
||||||
map_conversion.Northings = 1.0
|
map_conversion.Northings = 1.0
|
||||||
assert subject.enh2xyz([0.0, 0.0, 0.0]) == (-1.0, -1.0, 0.0)
|
assert subject.enh2xyz((0.0, 0.0, 0.0)) == (-1.0, -1.0, 0.0)
|
||||||
|
|||||||
@@ -79,11 +79,11 @@ class TestImportLibraryAttributes(NewFile):
|
|||||||
library = ifc.createIfcLibraryInformation("Name", "Version", None, "VersionDate", "Location", "Description")
|
library = ifc.createIfcLibraryInformation("Name", "Version", None, "VersionDate", "Location", "Description")
|
||||||
subject.import_library_attributes(library)
|
subject.import_library_attributes(library)
|
||||||
props = tool.Library.get_library_props()
|
props = tool.Library.get_library_props()
|
||||||
assert props.library_attributes.get("Name").string_value == "Name"
|
assert props.library_attributes["Name"].string_value == "Name"
|
||||||
assert props.library_attributes.get("Version").string_value == "Version"
|
assert props.library_attributes["Version"].string_value == "Version"
|
||||||
assert props.library_attributes.get("VersionDate").string_value == "VersionDate"
|
assert props.library_attributes["VersionDate"].string_value == "VersionDate"
|
||||||
assert props.library_attributes.get("Location").string_value == "Location"
|
assert props.library_attributes["Location"].string_value == "Location"
|
||||||
assert props.library_attributes.get("Description").string_value == "Description"
|
assert props.library_attributes["Description"].string_value == "Description"
|
||||||
|
|
||||||
|
|
||||||
class TestImportReferenceAttributes(NewFile):
|
class TestImportReferenceAttributes(NewFile):
|
||||||
@@ -92,11 +92,11 @@ class TestImportReferenceAttributes(NewFile):
|
|||||||
reference = ifc.createIfcLibraryReference("Location", "Identification", "Name", "Description", "Language")
|
reference = ifc.createIfcLibraryReference("Location", "Identification", "Name", "Description", "Language")
|
||||||
subject.import_reference_attributes(reference)
|
subject.import_reference_attributes(reference)
|
||||||
props = tool.Library.get_library_props()
|
props = tool.Library.get_library_props()
|
||||||
assert props.reference_attributes.get("Location").string_value == "Location"
|
assert props.reference_attributes["Location"].string_value == "Location"
|
||||||
assert props.reference_attributes.get("Identification").string_value == "Identification"
|
assert props.reference_attributes["Identification"].string_value == "Identification"
|
||||||
assert props.reference_attributes.get("Name").string_value == "Name"
|
assert props.reference_attributes["Name"].string_value == "Name"
|
||||||
assert props.reference_attributes.get("Description").string_value == "Description"
|
assert props.reference_attributes["Description"].string_value == "Description"
|
||||||
assert props.reference_attributes.get("Language").string_value == "Language"
|
assert props.reference_attributes["Language"].string_value == "Language"
|
||||||
|
|
||||||
|
|
||||||
class TestImportReferences(NewFile):
|
class TestImportReferences(NewFile):
|
||||||
|
|||||||
@@ -19,7 +19,9 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api.material
|
import ifcopenshell.api.material
|
||||||
|
import ifcopenshell.api.root
|
||||||
import ifcopenshell.api.style
|
import ifcopenshell.api.style
|
||||||
|
import ifcopenshell.api.type
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.representation
|
import ifcopenshell.util.representation
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class TestAddAddressAttribute(NewFile):
|
|||||||
subject().add_address_attribute("FacsimileNumbers")
|
subject().add_address_attribute("FacsimileNumbers")
|
||||||
subject().add_address_attribute("ElectronicMailAddresses")
|
subject().add_address_attribute("ElectronicMailAddresses")
|
||||||
subject().add_address_attribute("MessagingIDs")
|
subject().add_address_attribute("MessagingIDs")
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert len(props.address_lines) == 1
|
assert len(props.address_lines) == 1
|
||||||
assert len(props.telephone_numbers) == 1
|
assert len(props.telephone_numbers) == 1
|
||||||
assert len(props.facsimile_numbers) == 1
|
assert len(props.facsimile_numbers) == 1
|
||||||
@@ -49,7 +49,7 @@ class TestAddPersonAttribute(NewFile):
|
|||||||
subject().add_person_attribute("MiddleNames")
|
subject().add_person_attribute("MiddleNames")
|
||||||
subject().add_person_attribute("PrefixTitles")
|
subject().add_person_attribute("PrefixTitles")
|
||||||
subject().add_person_attribute("SuffixTitles")
|
subject().add_person_attribute("SuffixTitles")
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert len(props.middle_names) == 1
|
assert len(props.middle_names) == 1
|
||||||
assert len(props.prefix_titles) == 1
|
assert len(props.prefix_titles) == 1
|
||||||
assert len(props.suffix_titles) == 1
|
assert len(props.suffix_titles) == 1
|
||||||
@@ -61,7 +61,8 @@ class TestClearActor(NewFile):
|
|||||||
actor = ifc.createIfcActor()
|
actor = ifc.createIfcActor()
|
||||||
subject().set_actor(actor)
|
subject().set_actor(actor)
|
||||||
subject().clear_actor()
|
subject().clear_actor()
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_actor_id == 0
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_actor_id == 0
|
||||||
|
|
||||||
|
|
||||||
class TestClearAddress(NewFile):
|
class TestClearAddress(NewFile):
|
||||||
@@ -70,12 +71,13 @@ class TestClearAddress(NewFile):
|
|||||||
address = ifc.createIfcPostalAddress()
|
address = ifc.createIfcPostalAddress()
|
||||||
subject().set_address(address)
|
subject().set_address(address)
|
||||||
subject().clear_address()
|
subject().clear_address()
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_address_id == 0
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_address_id == 0
|
||||||
|
|
||||||
|
|
||||||
class TestClearOrganisation(NewFile):
|
class TestClearOrganisation(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
props.active_organisation_id = 1
|
props.active_organisation_id = 1
|
||||||
subject().clear_organisation()
|
subject().clear_organisation()
|
||||||
assert props.active_organisation_id == 0
|
assert props.active_organisation_id == 0
|
||||||
@@ -83,7 +85,7 @@ class TestClearOrganisation(NewFile):
|
|||||||
|
|
||||||
class TestClearPerson(NewFile):
|
class TestClearPerson(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
props.active_person_id = 1
|
props.active_person_id = 1
|
||||||
subject().clear_person()
|
subject().clear_person()
|
||||||
assert props.active_person_id == 0
|
assert props.active_person_id == 0
|
||||||
@@ -94,14 +96,16 @@ class TestClearRole(NewFile):
|
|||||||
role = ifcopenshell.file().createIfcActorRole()
|
role = ifcopenshell.file().createIfcActorRole()
|
||||||
subject().set_role(role)
|
subject().set_role(role)
|
||||||
subject().clear_role()
|
subject().clear_role()
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_role_id == 0
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_role_id == 0
|
||||||
|
|
||||||
|
|
||||||
class TestClearUser(NewFile):
|
class TestClearUser(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
TestSetUser().test_run()
|
TestSetUser().test_run()
|
||||||
subject.clear_user()
|
subject.clear_user()
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_user_id == 0
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_user_id == 0
|
||||||
|
|
||||||
|
|
||||||
class TestExportActorAttributes(NewFile):
|
class TestExportActorAttributes(NewFile):
|
||||||
@@ -288,11 +292,11 @@ class TestImportActorAttributes(NewFile):
|
|||||||
actor.ObjectType = "ObjectType"
|
actor.ObjectType = "ObjectType"
|
||||||
subject.set_actor(actor)
|
subject.set_actor(actor)
|
||||||
subject.import_actor_attributes(actor)
|
subject.import_actor_attributes(actor)
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.actor_attributes.get("GlobalId").string_value == "GlobalId"
|
assert props.actor_attributes["GlobalId"].string_value == "GlobalId"
|
||||||
assert props.actor_attributes.get("Name").string_value == "Name"
|
assert props.actor_attributes["Name"].string_value == "Name"
|
||||||
assert props.actor_attributes.get("Description").string_value == "Description"
|
assert props.actor_attributes["Description"].string_value == "Description"
|
||||||
assert props.actor_attributes.get("ObjectType").string_value == "ObjectType"
|
assert props.actor_attributes["ObjectType"].string_value == "ObjectType"
|
||||||
|
|
||||||
def test_importing_an_occupant(self):
|
def test_importing_an_occupant(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -305,12 +309,12 @@ class TestImportActorAttributes(NewFile):
|
|||||||
actor.PredefinedType = "TENANT"
|
actor.PredefinedType = "TENANT"
|
||||||
subject.set_actor(actor)
|
subject.set_actor(actor)
|
||||||
subject.import_actor_attributes(actor)
|
subject.import_actor_attributes(actor)
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.actor_attributes.get("GlobalId").string_value == "GlobalId"
|
assert props.actor_attributes["GlobalId"].string_value == "GlobalId"
|
||||||
assert props.actor_attributes.get("Name").string_value == "Name"
|
assert props.actor_attributes["Name"].string_value == "Name"
|
||||||
assert props.actor_attributes.get("Description").string_value == "Description"
|
assert props.actor_attributes["Description"].string_value == "Description"
|
||||||
assert props.actor_attributes.get("ObjectType").string_value == "ObjectType"
|
assert props.actor_attributes["ObjectType"].string_value == "ObjectType"
|
||||||
assert props.actor_attributes.get("PredefinedType").enum_value == "TENANT"
|
assert props.actor_attributes["PredefinedType"].enum_value == "TENANT"
|
||||||
|
|
||||||
|
|
||||||
class TestImportAddressAttributes(NewFile):
|
class TestImportAddressAttributes(NewFile):
|
||||||
@@ -330,16 +334,16 @@ class TestImportAddressAttributes(NewFile):
|
|||||||
address.Country = "Country"
|
address.Country = "Country"
|
||||||
subject().set_address(address)
|
subject().set_address(address)
|
||||||
subject().import_address_attributes()
|
subject().import_address_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.address_attributes.get("Purpose").enum_value == "USERDEFINED"
|
assert props.address_attributes["Purpose"].enum_value == "USERDEFINED"
|
||||||
assert props.address_attributes.get("Description").string_value == "Description"
|
assert props.address_attributes["Description"].string_value == "Description"
|
||||||
assert props.address_attributes.get("UserDefinedPurpose").string_value == "UserDefinedPurpose"
|
assert props.address_attributes["UserDefinedPurpose"].string_value == "UserDefinedPurpose"
|
||||||
assert props.address_attributes.get("InternalLocation").string_value == "InternalLocation"
|
assert props.address_attributes["InternalLocation"].string_value == "InternalLocation"
|
||||||
assert props.address_attributes.get("PostalBox").string_value == "PostalBox"
|
assert props.address_attributes["PostalBox"].string_value == "PostalBox"
|
||||||
assert props.address_attributes.get("Town").string_value == "Town"
|
assert props.address_attributes["Town"].string_value == "Town"
|
||||||
assert props.address_attributes.get("Region").string_value == "Region"
|
assert props.address_attributes["Region"].string_value == "Region"
|
||||||
assert props.address_attributes.get("PostalCode").string_value == "PostalCode"
|
assert props.address_attributes["PostalCode"].string_value == "PostalCode"
|
||||||
assert props.address_attributes.get("Country").string_value == "Country"
|
assert props.address_attributes["Country"].string_value == "Country"
|
||||||
assert len(props.address_lines) == 2
|
assert len(props.address_lines) == 2
|
||||||
assert props.address_lines[0].name == "Address"
|
assert props.address_lines[0].name == "Address"
|
||||||
assert props.address_lines[1].name == "Lines"
|
assert props.address_lines[1].name == "Lines"
|
||||||
@@ -351,8 +355,8 @@ class TestImportAddressAttributes(NewFile):
|
|||||||
address.Purpose = "OFFICE"
|
address.Purpose = "OFFICE"
|
||||||
subject().set_address(address)
|
subject().set_address(address)
|
||||||
subject().import_address_attributes()
|
subject().import_address_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.address_attributes.get("Purpose").enum_value == "OFFICE"
|
assert props.address_attributes["Purpose"].enum_value == "OFFICE"
|
||||||
assert len(props.address_lines) == 0
|
assert len(props.address_lines) == 0
|
||||||
|
|
||||||
def test_importing_a_telecom_address(self):
|
def test_importing_a_telecom_address(self):
|
||||||
@@ -370,10 +374,10 @@ class TestImportAddressAttributes(NewFile):
|
|||||||
address.MessagingIDs = ["Messaging", "IDs"]
|
address.MessagingIDs = ["Messaging", "IDs"]
|
||||||
subject().set_address(address)
|
subject().set_address(address)
|
||||||
subject().import_address_attributes()
|
subject().import_address_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.address_attributes.get("Purpose").enum_value == "USERDEFINED"
|
assert props.address_attributes["Purpose"].enum_value == "USERDEFINED"
|
||||||
assert props.address_attributes.get("Description").string_value == "Description"
|
assert props.address_attributes["Description"].string_value == "Description"
|
||||||
assert props.address_attributes.get("UserDefinedPurpose").string_value == "UserDefinedPurpose"
|
assert props.address_attributes["UserDefinedPurpose"].string_value == "UserDefinedPurpose"
|
||||||
assert [a.name for a in props.telephone_numbers] == ["Telephone", "Numbers"]
|
assert [a.name for a in props.telephone_numbers] == ["Telephone", "Numbers"]
|
||||||
assert [a.name for a in props.facsimile_numbers] == ["Facsimile", "Numbers"]
|
assert [a.name for a in props.facsimile_numbers] == ["Facsimile", "Numbers"]
|
||||||
assert [a.name for a in props.electronic_mail_addresses] == ["Electronic", "Mail", "Addresses"]
|
assert [a.name for a in props.electronic_mail_addresses] == ["Electronic", "Mail", "Addresses"]
|
||||||
@@ -386,8 +390,8 @@ class TestImportAddressAttributes(NewFile):
|
|||||||
address.Purpose = "OFFICE"
|
address.Purpose = "OFFICE"
|
||||||
subject().set_address(address)
|
subject().set_address(address)
|
||||||
subject().import_address_attributes()
|
subject().import_address_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.address_attributes.get("Purpose").enum_value == "OFFICE"
|
assert props.address_attributes["Purpose"].enum_value == "OFFICE"
|
||||||
assert len(props.telephone_numbers) == 0
|
assert len(props.telephone_numbers) == 0
|
||||||
assert len(props.facsimile_numbers) == 0
|
assert len(props.facsimile_numbers) == 0
|
||||||
assert len(props.electronic_mail_addresses) == 0
|
assert len(props.electronic_mail_addresses) == 0
|
||||||
@@ -404,10 +408,10 @@ class TestImportOrganisationAttributes(NewFile):
|
|||||||
organisation.Description = "Description"
|
organisation.Description = "Description"
|
||||||
subject().set_organisation(organisation)
|
subject().set_organisation(organisation)
|
||||||
subject().import_organisation_attributes()
|
subject().import_organisation_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.organisation_attributes.get("Identification").string_value == "Identification"
|
assert props.organisation_attributes["Identification"].string_value == "Identification"
|
||||||
assert props.organisation_attributes.get("Name").string_value == "Name"
|
assert props.organisation_attributes["Name"].string_value == "Name"
|
||||||
assert props.organisation_attributes.get("Description").string_value == "Description"
|
assert props.organisation_attributes["Description"].string_value == "Description"
|
||||||
|
|
||||||
def test_overwriting_a_previous_import(self):
|
def test_overwriting_a_previous_import(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -420,9 +424,9 @@ class TestImportOrganisationAttributes(NewFile):
|
|||||||
organisation.Identification = "Identification2"
|
organisation.Identification = "Identification2"
|
||||||
organisation.Description = None
|
organisation.Description = None
|
||||||
subject().import_organisation_attributes()
|
subject().import_organisation_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.organisation_attributes.get("Identification").string_value == "Identification2"
|
assert props.organisation_attributes["Identification"].string_value == "Identification2"
|
||||||
assert props.organisation_attributes.get("Description").string_value == ""
|
assert props.organisation_attributes["Description"].string_value == ""
|
||||||
|
|
||||||
|
|
||||||
class TestImportPersonAttributes(NewFile):
|
class TestImportPersonAttributes(NewFile):
|
||||||
@@ -438,10 +442,10 @@ class TestImportPersonAttributes(NewFile):
|
|||||||
person.SuffixTitles = ("suffix", "titles")
|
person.SuffixTitles = ("suffix", "titles")
|
||||||
subject().set_person(person)
|
subject().set_person(person)
|
||||||
subject().import_person_attributes()
|
subject().import_person_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.person_attributes.get("Identification").string_value == "identification"
|
assert props.person_attributes["Identification"].string_value == "identification"
|
||||||
assert props.person_attributes.get("GivenName").string_value == "given_name"
|
assert props.person_attributes["GivenName"].string_value == "given_name"
|
||||||
assert props.person_attributes.get("FamilyName").string_value == "family_name"
|
assert props.person_attributes["FamilyName"].string_value == "family_name"
|
||||||
assert len(props.middle_names) == 2
|
assert len(props.middle_names) == 2
|
||||||
assert props.middle_names[0].name == "middle"
|
assert props.middle_names[0].name == "middle"
|
||||||
assert props.middle_names[1].name == "names"
|
assert props.middle_names[1].name == "names"
|
||||||
@@ -463,9 +467,9 @@ class TestImportPersonAttributes(NewFile):
|
|||||||
person.Identification = "identification2"
|
person.Identification = "identification2"
|
||||||
person.GivenName = None
|
person.GivenName = None
|
||||||
subject().import_person_attributes()
|
subject().import_person_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.person_attributes.get("Identification").string_value == "identification2"
|
assert props.person_attributes["Identification"].string_value == "identification2"
|
||||||
assert props.person_attributes.get("GivenName").string_value == ""
|
assert props.person_attributes["GivenName"].string_value == ""
|
||||||
|
|
||||||
|
|
||||||
class TestImportRoleAttributes(NewFile):
|
class TestImportRoleAttributes(NewFile):
|
||||||
@@ -478,10 +482,10 @@ class TestImportRoleAttributes(NewFile):
|
|||||||
role.Description = "Description"
|
role.Description = "Description"
|
||||||
subject().set_role(role)
|
subject().set_role(role)
|
||||||
subject().import_role_attributes()
|
subject().import_role_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.role_attributes.get("Role").enum_value == "USERDEFINED"
|
assert props.role_attributes["Role"].enum_value == "USERDEFINED"
|
||||||
assert props.role_attributes.get("UserDefinedRole").string_value == "UserDefinedRole"
|
assert props.role_attributes["UserDefinedRole"].string_value == "UserDefinedRole"
|
||||||
assert props.role_attributes.get("Description").string_value == "Description"
|
assert props.role_attributes["Description"].string_value == "Description"
|
||||||
|
|
||||||
def test_importing_twice(self):
|
def test_importing_twice(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -492,8 +496,8 @@ class TestImportRoleAttributes(NewFile):
|
|||||||
subject().import_role_attributes()
|
subject().import_role_attributes()
|
||||||
role.Role = "ARCHITECT"
|
role.Role = "ARCHITECT"
|
||||||
subject().import_role_attributes()
|
subject().import_role_attributes()
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert props.role_attributes.get("Role").enum_value == "ARCHITECT"
|
assert props.role_attributes["Role"].enum_value == "ARCHITECT"
|
||||||
|
|
||||||
|
|
||||||
class TestRemoveAddressAttribute(NewFile):
|
class TestRemoveAddressAttribute(NewFile):
|
||||||
@@ -503,7 +507,7 @@ class TestRemoveAddressAttribute(NewFile):
|
|||||||
subject().remove_address_attribute("FacsimileNumbers", 0)
|
subject().remove_address_attribute("FacsimileNumbers", 0)
|
||||||
subject().remove_address_attribute("ElectronicMailAddresses", 0)
|
subject().remove_address_attribute("ElectronicMailAddresses", 0)
|
||||||
subject().remove_address_attribute("MessagingIDs", 0)
|
subject().remove_address_attribute("MessagingIDs", 0)
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert len(props.address_lines) == 0
|
assert len(props.address_lines) == 0
|
||||||
assert len(props.telephone_numbers) == 0
|
assert len(props.telephone_numbers) == 0
|
||||||
assert len(props.facsimile_numbers) == 0
|
assert len(props.facsimile_numbers) == 0
|
||||||
@@ -519,7 +523,7 @@ class TestRemovePersonAttribute(NewFile):
|
|||||||
subject().remove_person_attribute("PrefixTitles", 0)
|
subject().remove_person_attribute("PrefixTitles", 0)
|
||||||
subject().add_person_attribute("SuffixTitles")
|
subject().add_person_attribute("SuffixTitles")
|
||||||
subject().remove_person_attribute("SuffixTitles", 0)
|
subject().remove_person_attribute("SuffixTitles", 0)
|
||||||
props = bpy.context.scene.BIMOwnerProperties
|
props = subject.get_owner_props()
|
||||||
assert len(props.middle_names) == 0
|
assert len(props.middle_names) == 0
|
||||||
assert len(props.prefix_titles) == 0
|
assert len(props.prefix_titles) == 0
|
||||||
assert len(props.suffix_titles) == 0
|
assert len(props.suffix_titles) == 0
|
||||||
@@ -530,7 +534,8 @@ class TestSetActor(NewFile):
|
|||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
actor = ifc.createIfcActor()
|
actor = ifc.createIfcActor()
|
||||||
subject().set_actor(actor)
|
subject().set_actor(actor)
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_actor_id == actor.id()
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_actor_id == actor.id()
|
||||||
|
|
||||||
|
|
||||||
class TestSetAddress(NewFile):
|
class TestSetAddress(NewFile):
|
||||||
@@ -538,28 +543,32 @@ class TestSetAddress(NewFile):
|
|||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
address = ifc.createIfcPostalAddress()
|
address = ifc.createIfcPostalAddress()
|
||||||
subject().set_address(address)
|
subject().set_address(address)
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_address_id == address.id()
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_address_id == address.id()
|
||||||
|
|
||||||
|
|
||||||
class TestSetOrganisation(NewFile):
|
class TestSetOrganisation(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
organisation = ifcopenshell.file().createIfcOrganization()
|
organisation = ifcopenshell.file().createIfcOrganization()
|
||||||
subject().set_organisation(organisation)
|
subject().set_organisation(organisation)
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_organisation_id == organisation.id()
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_organisation_id == organisation.id()
|
||||||
|
|
||||||
|
|
||||||
class TestSetPerson(NewFile):
|
class TestSetPerson(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
person = ifcopenshell.file().createIfcPerson()
|
person = ifcopenshell.file().createIfcPerson()
|
||||||
subject().set_person(person)
|
subject().set_person(person)
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_person_id == person.id()
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_person_id == person.id()
|
||||||
|
|
||||||
|
|
||||||
class TestSetRole(NewFile):
|
class TestSetRole(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
role = ifcopenshell.file().createIfcActorRole()
|
role = ifcopenshell.file().createIfcActorRole()
|
||||||
subject().set_role(role)
|
subject().set_role(role)
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_role_id == role.id()
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_role_id == role.id()
|
||||||
|
|
||||||
|
|
||||||
class TestSetUser(NewFile):
|
class TestSetUser(NewFile):
|
||||||
@@ -568,4 +577,5 @@ class TestSetUser(NewFile):
|
|||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
user = ifc.createIfcPersonAndOrganization()
|
user = ifc.createIfcPersonAndOrganization()
|
||||||
subject.set_user(user)
|
subject.set_user(user)
|
||||||
assert bpy.context.scene.BIMOwnerProperties.active_user_id == user.id()
|
props = subject.get_owner_props()
|
||||||
|
assert props.active_user_id == user.id()
|
||||||
|
|||||||
@@ -391,8 +391,8 @@ class TestImportSurfaceAttributes(NewFile):
|
|||||||
props = tool.Style.get_style_props()
|
props = tool.Style.get_style_props()
|
||||||
style = ifc.create_entity("IfcSurfaceStyle", "Name", "BOTH")
|
style = ifc.create_entity("IfcSurfaceStyle", "Name", "BOTH")
|
||||||
subject.import_surface_attributes(style)
|
subject.import_surface_attributes(style)
|
||||||
assert props.attributes.get("Name").string_value == "Name"
|
assert props.attributes["Name"].string_value == "Name"
|
||||||
assert props.attributes.get("Side").enum_value == "BOTH"
|
assert props.attributes["Side"].enum_value == "BOTH"
|
||||||
|
|
||||||
def test_importing_surface_attributes_twice(self):
|
def test_importing_surface_attributes_twice(self):
|
||||||
tool.Ifc.set(ifc := ifcopenshell.file())
|
tool.Ifc.set(ifc := ifcopenshell.file())
|
||||||
@@ -400,12 +400,12 @@ class TestImportSurfaceAttributes(NewFile):
|
|||||||
props = tool.Style.get_style_props()
|
props = tool.Style.get_style_props()
|
||||||
subject.import_surface_attributes(style)
|
subject.import_surface_attributes(style)
|
||||||
assert len(props.attributes) == 2
|
assert len(props.attributes) == 2
|
||||||
assert props.attributes.get("Name").string_value == "Name"
|
assert props.attributes["Name"].string_value == "Name"
|
||||||
assert props.attributes.get("Side").enum_value == "BOTH"
|
assert props.attributes["Side"].enum_value == "BOTH"
|
||||||
subject.import_surface_attributes(style)
|
subject.import_surface_attributes(style)
|
||||||
assert len(props.attributes) == 2
|
assert len(props.attributes) == 2
|
||||||
assert props.attributes.get("Name").string_value == "Name"
|
assert props.attributes["Name"].string_value == "Name"
|
||||||
assert props.attributes.get("Side").enum_value == "BOTH"
|
assert props.attributes["Side"].enum_value == "BOTH"
|
||||||
|
|
||||||
|
|
||||||
class TestImportPresentationStyles(NewFile):
|
class TestImportPresentationStyles(NewFile):
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
import ifcopenshell.util.unit
|
||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -43,6 +44,7 @@ class TestAddPorts(NewFile):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
obj.matrix_world = Euler((pi / 2, 0, pi / 2)).to_matrix().to_4x4() @ obj.matrix_world
|
obj.matrix_world = Euler((pi / 2, 0, pi / 2)).to_matrix().to_4x4() @ obj.matrix_world
|
||||||
# move origin
|
# move origin
|
||||||
|
assert isinstance(obj.data, bpy.types.Mesh)
|
||||||
for v in obj.data.vertices:
|
for v in obj.data.vertices:
|
||||||
v.co += Vector((0, 0, 2.5))
|
v.co += Vector((0, 0, 2.5))
|
||||||
return obj, element
|
return obj, element
|
||||||
@@ -90,6 +92,7 @@ class TestAddPorts(NewFile):
|
|||||||
|
|
||||||
class TestCreateEmptyAtCursorWithElementOrientation(NewFile):
|
class TestCreateEmptyAtCursorWithElementOrientation(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc().set(ifc)
|
tool.Ifc().set(ifc)
|
||||||
obj = bpy.data.objects.new("Object", None)
|
obj = bpy.data.objects.new("Object", None)
|
||||||
@@ -175,10 +178,10 @@ class TestImportSystemAttributes(NewFile):
|
|||||||
system.ObjectType = "ObjectType"
|
system.ObjectType = "ObjectType"
|
||||||
subject().import_system_attributes(system)
|
subject().import_system_attributes(system)
|
||||||
props = tool.System.get_system_props()
|
props = tool.System.get_system_props()
|
||||||
assert props.system_attributes.get("GlobalId").string_value == "GlobalId"
|
assert props.system_attributes["GlobalId"].string_value == "GlobalId"
|
||||||
assert props.system_attributes.get("Name").string_value == "Name"
|
assert props.system_attributes["Name"].string_value == "Name"
|
||||||
assert props.system_attributes.get("Description").string_value == "Description"
|
assert props.system_attributes["Description"].string_value == "Description"
|
||||||
assert props.system_attributes.get("ObjectType").string_value == "ObjectType"
|
assert props.system_attributes["ObjectType"].string_value == "ObjectType"
|
||||||
|
|
||||||
def test_importing_a_building_system(self):
|
def test_importing_a_building_system(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -192,12 +195,12 @@ class TestImportSystemAttributes(NewFile):
|
|||||||
system.LongName = "LongName"
|
system.LongName = "LongName"
|
||||||
subject().import_system_attributes(system)
|
subject().import_system_attributes(system)
|
||||||
props = tool.System.get_system_props()
|
props = tool.System.get_system_props()
|
||||||
assert props.system_attributes.get("GlobalId").string_value == "GlobalId"
|
assert props.system_attributes["GlobalId"].string_value == "GlobalId"
|
||||||
assert props.system_attributes.get("Name").string_value == "Name"
|
assert props.system_attributes["Name"].string_value == "Name"
|
||||||
assert props.system_attributes.get("Description").string_value == "Description"
|
assert props.system_attributes["Description"].string_value == "Description"
|
||||||
assert props.system_attributes.get("ObjectType").string_value == "ObjectType"
|
assert props.system_attributes["ObjectType"].string_value == "ObjectType"
|
||||||
assert props.system_attributes.get("PredefinedType").enum_value == "SHADING"
|
assert props.system_attributes["PredefinedType"].enum_value == "SHADING"
|
||||||
assert props.system_attributes.get("LongName").string_value == "LongName"
|
assert props.system_attributes["LongName"].string_value == "LongName"
|
||||||
|
|
||||||
def test_importing_a_distribution_system(self):
|
def test_importing_a_distribution_system(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -211,12 +214,12 @@ class TestImportSystemAttributes(NewFile):
|
|||||||
system.LongName = "LongName"
|
system.LongName = "LongName"
|
||||||
subject().import_system_attributes(system)
|
subject().import_system_attributes(system)
|
||||||
props = tool.System.get_system_props()
|
props = tool.System.get_system_props()
|
||||||
assert props.system_attributes.get("GlobalId").string_value == "GlobalId"
|
assert props.system_attributes["GlobalId"].string_value == "GlobalId"
|
||||||
assert props.system_attributes.get("Name").string_value == "Name"
|
assert props.system_attributes["Name"].string_value == "Name"
|
||||||
assert props.system_attributes.get("Description").string_value == "Description"
|
assert props.system_attributes["Description"].string_value == "Description"
|
||||||
assert props.system_attributes.get("ObjectType").string_value == "ObjectType"
|
assert props.system_attributes["ObjectType"].string_value == "ObjectType"
|
||||||
assert props.system_attributes.get("PredefinedType").enum_value == "ELECTRICAL"
|
assert props.system_attributes["PredefinedType"].enum_value == "ELECTRICAL"
|
||||||
assert props.system_attributes.get("LongName").string_value == "LongName"
|
assert props.system_attributes["LongName"].string_value == "LongName"
|
||||||
|
|
||||||
|
|
||||||
class TestImportSystems(NewFile):
|
class TestImportSystems(NewFile):
|
||||||
@@ -245,7 +248,7 @@ class TestLoadPorts(NewFile):
|
|||||||
port = ifc.create_entity("IfcDistributionPort")
|
port = ifc.create_entity("IfcDistributionPort")
|
||||||
subject.load_ports(element, [port])
|
subject.load_ports(element, [port])
|
||||||
obj = tool.Ifc.get_object(port)
|
obj = tool.Ifc.get_object(port)
|
||||||
assert obj
|
assert isinstance(obj, bpy.types.Object)
|
||||||
assert obj.users_collection
|
assert obj.users_collection
|
||||||
assert list(obj.location) == [0, 0, 0]
|
assert list(obj.location) == [0, 0, 0]
|
||||||
|
|
||||||
@@ -262,6 +265,7 @@ class TestRunRootAssignClass(NewFile):
|
|||||||
|
|
||||||
class TestSelectSystemProducts(NewFile):
|
class TestSelectSystemProducts(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc().set(ifc)
|
tool.Ifc().set(ifc)
|
||||||
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcPump")
|
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcPump")
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api.root
|
||||||
|
import ifcopenshell.api.type
|
||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from test.bim.bootstrap import NewFile
|
from test.bim.bootstrap import NewFile
|
||||||
@@ -153,9 +155,9 @@ class TestGetTypeOccurrences(NewFile):
|
|||||||
def test_run(self):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
tool.Ifc.set(ifc)
|
||||||
wall_type = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcWallType")
|
wall_type = ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcWallType")
|
||||||
wall = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcWall")
|
wall = ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcWall")
|
||||||
ifcopenshell.api.run("type.assign_type", ifc, related_objects=[wall], relating_type=wall_type)
|
ifcopenshell.api.type.assign_type(ifc, related_objects=[wall], relating_type=wall_type)
|
||||||
assert subject.get_type_occurrences(wall_type) == (wall,)
|
assert subject.get_type_occurrences(wall_type) == (wall,)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class TestExportUnitAttributes(NewFile):
|
|||||||
|
|
||||||
class TestGetSceneUnitName(NewFile):
|
class TestGetSceneUnitName(NewFile):
|
||||||
def test_getting_an_imperial_name(self):
|
def test_getting_an_imperial_name(self):
|
||||||
|
assert bpy.context.scene
|
||||||
props = tool.Blender.get_bim_props()
|
props = tool.Blender.get_bim_props()
|
||||||
bpy.context.scene.unit_settings.system = "IMPERIAL"
|
bpy.context.scene.unit_settings.system = "IMPERIAL"
|
||||||
bpy.context.scene.unit_settings.length_unit = "MILES"
|
bpy.context.scene.unit_settings.length_unit = "MILES"
|
||||||
@@ -130,12 +131,14 @@ class TestGetSceneUnitName(NewFile):
|
|||||||
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
assert subject.get_scene_unit_name("VOLUMEUNIT") == "cubic inch"
|
||||||
|
|
||||||
def test_getting_a_name_with_no_unit_system(self):
|
def test_getting_a_name_with_no_unit_system(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.unit_settings.system = "NONE"
|
bpy.context.scene.unit_settings.system = "NONE"
|
||||||
assert subject.get_scene_unit_name("LENGTHUNIT") == "foot"
|
assert subject.get_scene_unit_name("LENGTHUNIT") == "foot"
|
||||||
|
|
||||||
|
|
||||||
class TestGetSceneUnitSIPrefix:
|
class TestGetSceneUnitSIPrefix:
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
bpy.context.scene.unit_settings.system = "METRIC"
|
bpy.context.scene.unit_settings.system = "METRIC"
|
||||||
bpy.context.scene.unit_settings.length_unit = "METERS"
|
bpy.context.scene.unit_settings.length_unit = "METERS"
|
||||||
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") is None
|
assert subject.get_scene_unit_si_prefix("LENGTHUNIT") is None
|
||||||
@@ -298,6 +301,7 @@ class TestImportUnits(NewFile):
|
|||||||
|
|
||||||
class TestIsSceneUnitMetric(NewFile):
|
class TestIsSceneUnitMetric(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
|
assert bpy.context.scene
|
||||||
props = bpy.context.scene.unit_settings
|
props = bpy.context.scene.unit_settings
|
||||||
props.system = "METRIC"
|
props.system = "METRIC"
|
||||||
assert subject.is_scene_unit_metric() is True
|
assert subject.is_scene_unit_metric() is True
|
||||||
|
|||||||
Reference in New Issue
Block a user