This commit is contained in:
Andrej730
2025-02-03 17:40:46 +05:00
parent ecd7282150
commit d4f44cb0a1
25 changed files with 165 additions and 74 deletions
@@ -78,7 +78,8 @@ class BoundaryDecorator:
unselected_edges = []
unselected_tris = []
for boundary in context.scene.BIMBoundaryProperties.boundaries:
props = tool.Boundary.get_boundary_props()
for boundary in props.boundaries:
obj = boundary.obj
if not obj or not obj.data: # A boundary may not have data if it has no connection geometry
continue
@@ -354,7 +354,9 @@ class EnableEditingBoundary(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bprops = context.active_object.BIMBoundaryProperties
obj = context.active_object
assert obj
bprops = tool.Boundary.get_object_boundary_props(obj)
bprops.is_editing = True
boundary = tool.Ifc.get_entity(context.active_object)
for ifc_attribute, blender_property in EDITABLE_ATTRIBUTES.items():
@@ -373,7 +375,9 @@ class DisableEditingBoundary(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bprops = context.active_object.BIMBoundaryProperties
obj = context.active_object
assert obj
bprops = tool.Boundary.get_object_boundary_props(obj)
bprops.is_editing = False
for ifc_attribute, blender_property in EDITABLE_ATTRIBUTES.items():
setattr(bprops, blender_property, None)
@@ -386,8 +390,10 @@ class EditBoundaryAttributes(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
bprops = context.active_object.BIMBoundaryProperties
boundary = tool.Ifc.get_entity(context.active_object)
obj = context.active_object
assert obj
bprops = tool.Boundary.get_object_boundary_props(obj)
boundary = tool.Ifc.get_entity(obj)
attributes = dict()
for ifc_attribute, blender_property in EDITABLE_ATTRIBUTES.items():
obj = getattr(bprops, blender_property, None)
@@ -519,6 +525,7 @@ class HideBoundaries(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = tool.Boundary.get_boundary_props()
to_delete = set()
spaces = set()
for obj in context.selected_objects:
@@ -538,7 +545,7 @@ class HideBoundaries(bpy.types.Operator, tool.Ifc.Operator):
for boundary, boundary_obj in to_delete:
tool.Ifc.unlink(element=boundary)
bpy.data.objects.remove(boundary_obj)
context.scene.BIMBoundaryProperties.boundaries.clear()
props.boundaries.clear()
return {"FINISHED"}
@@ -549,7 +556,7 @@ class DecorateBoundaries(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMBoundaryProperties
props = tool.Boundary.get_boundary_props()
# filter not decorated boundaries and add decorations for them
decorated_boundaries = set([i.obj for i in props.boundaries])
active_boundaries = set()
+14 -3
View File
@@ -30,23 +30,24 @@ from bpy.props import (
CollectionProperty,
)
import bonsai.tool as tool
from typing import TYPE_CHECKING, Union
def space_filter(self, object):
def space_filter(self: "BIMObjectBoundaryProperties", object: bpy.types.Object) -> bool:
entity = tool.Ifc.get_entity(object)
if entity:
return entity.is_a("IfcSpace") or entity.is_a("IfcExternalSpatialElement")
return False
def boundary_filter(self, object):
def boundary_filter(self: "BIMObjectBoundaryProperties", object: bpy.types.Object) -> bool:
entity = tool.Ifc.get_entity(object)
if entity:
return entity.is_a("IfcRelSpaceBoundary")
return False
def element_filter(self, object):
def element_filter(self: "BIMObjectBoundaryProperties", object: bpy.types.Object) -> bool:
entity = tool.Ifc.get_entity(object)
if entity:
return entity.is_a("IfcElement")
@@ -60,6 +61,16 @@ class BIMObjectBoundaryProperties(PropertyGroup):
parent_boundary: PointerProperty(name="ParentBoundary", type=bpy.types.Object, poll=boundary_filter)
corresponding_boundary: PointerProperty(name="CorrespondingBoundary", type=bpy.types.Object, poll=boundary_filter)
if TYPE_CHECKING:
is_editing: bool
relating_space: Union[bpy.types.Object, None]
related_building_element: Union[bpy.types.Object, None]
parent_boundary: Union[bpy.types.Object, None]
corresponding_boundary: Union[bpy.types.Object, None]
class BIMBoundaryProperties(PropertyGroup):
boundaries: bpy.props.CollectionProperty(type=ObjProperty)
if TYPE_CHECKING:
boundaries: bpy.types.bpy_prop_collection_idprop[ObjProperty]
+4 -2
View File
@@ -64,10 +64,12 @@ class BIM_PT_Boundary(Panel):
return entity.is_a("IfcRelSpaceBoundary")
def draw(self, context):
props = context.active_object.BIMObjectProperties
obj = context.active_object
assert obj
props = obj.BIMObjectProperties
ifc_file = tool.Ifc.get()
boundary = ifc_file.by_id(props.ifc_definition_id)
self.bprops = context.active_object.BIMBoundaryProperties
self.bprops = tool.Boundary.get_object_boundary_props(obj)
if self.bprops.is_editing:
row = self.layout.row(align=True)
row.operator("bim.edit_boundary_attributes", icon="CHECKMARK", text="Save Attributes")
+3 -2
View File
@@ -325,10 +325,11 @@ class CostItemQuantitiesData:
@classmethod
def process_quantity_names(cls):
active_task_index = bpy.context.scene.BIMWorkScheduleProperties.active_task_index
total_tasks = len(bpy.context.scene.BIMTaskTreeProperties.tasks)
tprops = tool.Sequence.get_task_tree_props()
total_tasks = len(tprops.tasks)
if not total_tasks or active_task_index >= total_tasks:
return []
ifc_definition_id = bpy.context.scene.BIMTaskTreeProperties.tasks[active_task_index].ifc_definition_id
ifc_definition_id = tprops.tasks[active_task_index].ifc_definition_id
element = tool.Ifc.get().by_id(ifc_definition_id)
names = set()
qtos = ifcopenshell.util.element.get_psets(element, qtos_only=True)
+2 -1
View File
@@ -19,6 +19,7 @@
import bpy
import bonsai.bim.helper
import bonsai.bim.module.cost.prop as CostProp
import bonsai.tool as tool
from bpy.types import Panel, UIList
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.cost.data import CostSchedulesData
@@ -461,7 +462,7 @@ class BIM_PT_cost_item_quantities(Panel):
total_cost_item_processes = len(self.props.cost_item_processes)
row2.label(text="Tasks ({})".format(total_cost_item_processes))
tprops = context.scene.BIMTaskTreeProperties
tprops = tool.Sequence.get_task_tree_props()
wprops = context.scene.BIMWorkScheduleProperties
if tprops.tasks and wprops.active_task_index < len(tprops.tasks):
if has_quantity_names:
@@ -422,7 +422,7 @@ class CreateDrawing(bpy.types.Operator):
self.svg_writer.create_blank_svg(svg_path).draw_underlay(context.scene.render.filepath).save()
return svg_path
def get_linework_contexts(self, ifc, target_view) -> LineworkContexts:
def get_linework_contexts(self, ifc: ifcopenshell.file, target_view: str) -> LineworkContexts:
plan_body_target_contexts = []
plan_body_model_contexts = []
model_body_target_contexts = []
@@ -42,6 +42,7 @@ import ifcopenshell.util.representation
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import bonsai.bim.handler
import bonsai.bim.helper
import bonsai.bim.schema
import bonsai.tool as tool
import bonsai.core.project as core
+6 -6
View File
@@ -128,7 +128,7 @@ class BIM_PT_project(Panel):
self.layout.use_property_decorate = False
self.layout.use_property_split = True
props = context.scene.BIMProperties
pprops = context.scene.BIMProjectProperties
pprops = self.props = tool.Project.get_project_props()
self.file = IfcStore.get_file()
if pprops.is_loading:
self.draw_advanced_loading_ui(context)
@@ -148,7 +148,7 @@ class BIM_PT_project(Panel):
self.draw_unsaved_project_ui(context)
def draw_advanced_loading_ui(self, context):
pprops = context.scene.BIMProjectProperties
pprops = self.props
prop_with_search(self.layout, pprops, "filter_mode")
if pprops.filter_mode in ["DECOMPOSITION", "IFC_CLASS", "IFC_TYPE"]:
row = self.layout.row(align=True)
@@ -222,7 +222,7 @@ class BIM_PT_project(Panel):
row.operator("bim.load_project_elements")
def draw_editing_buttons(self, context, row):
pprops = context.scene.BIMProjectProperties
pprops = self.props
if IfcStore.get_file():
if pprops.is_editing:
row.operator("bim.edit_header", icon="CHECKMARK", text="")
@@ -231,7 +231,7 @@ class BIM_PT_project(Panel):
row.operator("bim.enable_editing_header", icon="GREASEPENCIL", text="")
def draw_editable_file_info(self, context):
pprops = context.scene.BIMProjectProperties
pprops = self.props
if IfcStore.get_file():
row = self.layout.row(align=True)
@@ -316,7 +316,7 @@ class BIM_PT_new_project_wizard(Panel):
self.layout.use_property_split = True
props = context.scene.BIMProperties
pprops = context.scene.BIMProjectProperties
pprops = tool.Project.get_project_props()
prop_with_search(self.layout, pprops, "export_schema")
row = self.layout.row()
row.prop(context.scene.unit_settings, "system")
@@ -418,7 +418,7 @@ class BIM_PT_links(Panel):
bl_parent_id = "BIM_PT_tab_project_setup"
def draw(self, context):
self.props = context.scene.BIMProjectProperties
self.props = tool.Project.get_project_props()
row = self.layout.row(align=True)
row.operator("bim.link_ifc")
if self.props.links:
+6 -2
View File
@@ -55,7 +55,11 @@ class Data:
for name, data in sorted(psetqtos.items()):
pset = ifc_file.by_id(data["id"])
pset_uses = ifcopenshell.util.element.get_elements_by_pset(pset)
has_template = bool(tool.Pset.get_pset_template(name))
pset_template = tool.Pset.get_pset_template(name)
if has_template := bool(pset_template):
template_available_in_ui = pset_template
else:
template_available_in_ui = False
results.append(
{
"id": data["id"],
@@ -214,7 +218,7 @@ class TaskQtosData(Data):
@classmethod
def load(cls):
wprops = bpy.context.scene.BIMWorkScheduleProperties
tprops = bpy.context.scene.BIMTaskTreeProperties
tprops = tool.Sequence.get_task_tree_props()
ifc_definition_id = tprops.tasks[wprops.active_task_index].ifc_definition_id
cls.data = {"qtos": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), qtos_only=True)}
cls.is_loaded = True
@@ -491,14 +491,14 @@ class SavePsetAsTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOpera
pset_id: bpy.props.IntProperty()
def invoke(self, context, event):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
if tool.Blender.get_enum_safe(props, "pset_template_files") is None:
self.report({"ERROR"}, "No template files found. You can create one in Property Set Templates UI.")
return {"CANCELLED"}
return context.window_manager.invoke_props_dialog(self, width=250)
def draw(self, context):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
self.layout.prop(props, "pset_template_files", text="Template File")
def _execute(self, context):
+6 -7
View File
@@ -40,7 +40,7 @@ from typing import Any, Optional, TYPE_CHECKING
from typing_extensions import assert_never
if TYPE_CHECKING:
from bonsai.bim.module.pset.prop import IfcProperty
from bonsai.bim.module.pset.prop import IfcProperty, PsetProperties
def draw_property(prop: IfcProperty, layout: bpy.types.UILayout, copy_operator: Optional[str] = None) -> None:
@@ -73,7 +73,7 @@ def draw_single_property(prop: IfcProperty, layout: bpy.types.UILayout, copy_ope
def draw_enumerated_property(
prop: bpy.types.PropertyGroup, layout: bpy.types.UILayout, copy_operator: Optional[str] = None
prop: IfcProperty, layout: bpy.types.UILayout, copy_operator: Optional[str] = None
) -> None:
value_name = prop.metadata.get_value_name()
if not value_name:
@@ -99,7 +99,7 @@ def draw_psetqto_ui(
context: bpy.types.Context,
pset_id: int,
pset: dict[str, Any],
props: bpy.types.PropertyGroup,
props: PsetProperties,
layout: bpy.types.UILayout,
obj_type: tool.Ifc.OBJECT_TYPE,
allow_removing: bool = True,
@@ -219,9 +219,7 @@ def draw_psetqto_ui(
row.label(text="No Properties")
def draw_psetqto_editable_ui(
box: bpy.types.UILayout, props: bpy.types.PropertyGroup, prop: bpy.types.PropertyGroup
) -> None:
def draw_psetqto_editable_ui(box: bpy.types.UILayout, props: PsetProperties, prop: IfcProperty) -> None:
row = box.row(align=True)
draw_property(prop, row, copy_operator="bim.copy_property_to_selection")
@@ -493,7 +491,8 @@ class BIM_PT_task_qtos(Panel):
props = context.scene.BIMWorkScheduleProperties
if not props.active_work_schedule_id:
return False
total_tasks = len(context.scene.BIMTaskTreeProperties.tasks)
tprops = tool.Sequence.get_task_tree_props()
total_tasks = len(tprops.tasks)
if total_tasks > 0 and props.active_task_index < total_tasks:
return True
return False
@@ -126,13 +126,14 @@ class PsetTemplatesData:
if not cls.data["pset_template_files"]:
return []
if not IfcStore.pset_template_file:
IfcStore.pset_template_path = bpy.context.scene.BIMPsetTemplateProperties.pset_template_files
props = tool.PsetTemplate.get_pset_template_props()
IfcStore.pset_template_path = props.pset_template_files
IfcStore.pset_template_file = ifcopenshell.open(IfcStore.pset_template_path)
return [(str(t.id()), t.Name, "") for t in IfcStore.pset_template_file.by_type("IfcPropertySetTemplate")]
@classmethod
def pset_template(cls) -> dict[str, Any]:
props = bpy.context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
template_id = props.pset_templates
if not template_id:
return {}
@@ -145,7 +146,7 @@ class PsetTemplatesData:
@classmethod
def prop_templates(cls) -> list[dict[str, Any]]:
props = bpy.context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
template_id = props.pset_templates
if not template_id:
return []
@@ -49,7 +49,8 @@ class AddPsetTemplateFile(bpy.types.Operator):
template.write(filepath)
bonsai.bim.handler.refresh_ui_data()
bonsai.bim.schema.reload(tool.Ifc.get().schema)
context.scene.BIMPsetTemplateProperties.pset_template_files = filepath
props = tool.PsetTemplate.get_pset_template_props()
props.pset_template_files = filepath
tool.PsetTemplate.enable_editing_pset_template()
return {"FINISHED"}
@@ -67,7 +68,8 @@ class AddPsetTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOperator
self.template_file.write(IfcStore.pset_template_path)
bonsai.bim.handler.refresh_ui_data()
bonsai.bim.schema.reload(tool.Ifc.get().schema)
context.scene.BIMPsetTemplateProperties.pset_templates = str(template.id())
props = tool.PsetTemplate.get_pset_template_props()
props.pset_templates = str(template.id())
class RemovePsetTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOperator):
@@ -76,7 +78,7 @@ class RemovePsetTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOpera
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
current_pset_template_id = int(props.pset_templates)
if props.active_pset_template_id == current_pset_template_id:
bpy.ops.bim.disable_editing_pset_template()
@@ -107,7 +109,7 @@ class DisableEditingPsetTemplate(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
props.active_pset_template_id = 0
return {"FINISHED"}
@@ -130,7 +132,8 @@ class DeletePropEnum(bpy.types.Operator):
index: bpy.props.IntProperty()
def execute(self, context):
active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template
props = tool.PsetTemplate.get_pset_template_props()
active_prop = props.active_prop_template
active_prop.enum_values.remove(self.index)
return {"FINISHED"}
@@ -142,7 +145,8 @@ class AddPropEnum(bpy.types.Operator):
index: bpy.props.IntProperty()
def execute(self, context):
active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template
props = tool.PsetTemplate.get_pset_template_props()
active_prop = props.active_prop_template
active_prop.enum_values.add()
return {"FINISHED"}
@@ -153,7 +157,7 @@ class DisableEditingPropTemplate(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
props.active_prop_template_id = 0
return {"FINISHED"}
@@ -164,7 +168,7 @@ class EditPsetTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOperato
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
ifcopenshell.api.run(
"pset_template.edit_pset_template",
IfcStore.pset_template_file,
@@ -209,7 +213,7 @@ class RemovePsetTemplateFile(bpy.types.Operator):
bonsai.bim.schema.reload(tool.Ifc.get().schema)
# Ensure enum is valid after deletion.
self.props = context.scene.BIMPsetTemplateProperties
self.props = tool.PsetTemplate.get_pset_template_props()
if not tool.Blender.ensure_enum_is_valid(self.props, "pset_template_files"):
self.update_template_files_prop(context)
return {"FINISHED"}
@@ -226,7 +230,7 @@ class AddPropTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOperator
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
pset_template_id = props.active_pset_template_id or int(props.pset_templates)
prop_template = ifcopenshell.api.run(
"pset_template.add_prop_template",
@@ -264,7 +268,7 @@ class EditPropTemplate(bpy.types.Operator, tool.PsetTemplate.PsetTemplateOperato
def _execute(self, context):
assert IfcStore.pset_template_file
props = context.scene.BIMPsetTemplateProperties
props = tool.PsetTemplate.get_pset_template_props()
active_prop_template = props.active_prop_template
if props.active_prop_template.template_type == "P_ENUMERATEDVALUE":
data_type = props.active_prop_template.get_value_name()
@@ -36,7 +36,7 @@ class BIM_PT_pset_template(Panel):
if not PsetTemplatesData.is_loaded:
PsetTemplatesData.load()
self.props = context.scene.BIMPsetTemplateProperties
self.props = tool.PsetTemplate.get_pset_template_props()
row = self.layout.row(align=True)
if PsetTemplatesData.data["pset_template_files"]:
@@ -40,6 +40,7 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
from typing import TYPE_CHECKING
def getTaskColumns(self, context):
@@ -343,6 +344,26 @@ class Task(PropertyGroup):
is_predecessor: BoolProperty(name="Is Predecessor")
is_successor: BoolProperty(name="Is Successor")
if TYPE_CHECKING:
name: str
identification: str
ifc_definition_id: int
has_children: bool
is_selected: bool
is_expanded: bool
has_bar_visual: bool
level_index: int
duration: str
start: str
finish: str
calendar: str
derived_start: str
derived_finish: str
derived_duration: str
derived_calendar: str
is_predecessor: bool
is_successor: bool
class WorkPlan(PropertyGroup):
name: StringProperty(name="Name")
@@ -479,6 +500,9 @@ class BIMTaskTreeProperties(PropertyGroup):
# In Blender if you add many collection items it makes other property access in the same group really slow.
tasks: CollectionProperty(name="Tasks", type=Task)
if TYPE_CHECKING:
tasks: bpy.types.bpy_prop_collection_idprop[Task]
class WorkCalendar(PropertyGroup):
name: StringProperty(name="Name")
+4 -3
View File
@@ -156,7 +156,7 @@ class BIM_PT_work_schedules(Panel):
if not WorkScheduleData.is_loaded:
WorkScheduleData.load()
self.props = context.scene.BIMWorkScheduleProperties
self.tprops = context.scene.BIMTaskTreeProperties
self.tprops = tool.Sequence.get_task_tree_props()
if not self.props.active_work_schedule_id:
row = self.layout.row(align=True)
@@ -649,7 +649,8 @@ class BIM_PT_task_icom(Panel):
props = context.scene.BIMWorkScheduleProperties
if not props.active_work_schedule_id:
return False
total_tasks = len(context.scene.BIMTaskTreeProperties.tasks)
tprops = tool.Sequence.get_task_tree_props()
total_tasks = len(tprops.tasks)
if total_tasks > 0 and props.active_task_index < total_tasks:
return True
return False
@@ -659,7 +660,7 @@ class BIM_PT_task_icom(Panel):
TaskICOMData.load()
self.props = context.scene.BIMWorkScheduleProperties
self.tprops = context.scene.BIMTaskTreeProperties
self.tprops = tool.Sequence.get_task_tree_props()
task = self.tprops.tasks[self.props.active_task_index]
grid = self.layout.grid_flow(columns=3, even_columns=True)
+7
View File
@@ -169,6 +169,9 @@ class StrProperty(PropertyGroup):
class ObjProperty(PropertyGroup):
obj: bpy.props.PointerProperty(type=bpy.types.Object)
if TYPE_CHECKING:
obj: Union[bpy.types.Object, None]
def update_single_file(self: "MultipleFileSelect", context: bpy.types.Context) -> None:
self.file_list.clear()
@@ -180,6 +183,10 @@ class MultipleFileSelect(PropertyGroup):
single_file: bpy.props.StringProperty(name="Single File Path", description="", update=update_single_file)
file_list: bpy.props.CollectionProperty(type=StrProperty)
if TYPE_CHECKING:
single_file: str
file_list: bpy.types.bpy_prop_collection_idprop[StrProperty]
def set_file_list(self, dirname: str, files: list[str]) -> None:
self.file_list.clear()
+2 -3
View File
@@ -194,9 +194,8 @@ class Blender(bonsai.core.tool.Blender):
elif obj_type == "MaterialSetItem":
return bpy.data.objects.get(obj).BIMObjectMaterialProperties.active_material_set_item_id
elif obj_type == "Task":
return context.scene.BIMTaskTreeProperties.tasks[
context.scene.BIMWorkScheduleProperties.active_task_index
].ifc_definition_id
tprops = tool.Sequence.get_task_tree_props()
return tprops.tasks[context.scene.BIMWorkScheduleProperties.active_task_index].ifc_definition_id
elif obj_type == "Cost":
return context.scene.BIMCostProperties.cost_items[
context.scene.BIMCostProperties.active_cost_item_index
+15 -2
View File
@@ -16,15 +16,27 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import bpy
import mathutils
import bonsai.core.tool
import bonsai.tool as tool
from mathutils import Matrix, Vector
from typing import Any, Sequence
from typing import Any, Sequence, TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.boundary.prop import BIMBoundaryProperties, BIMObjectBoundaryProperties
class Boundary(bonsai.core.tool.Boundary):
@classmethod
def get_boundary_props(cls) -> BIMBoundaryProperties:
return bpy.context.scene.BIMBoundaryProperties
@classmethod
def get_object_boundary_props(cls, obj: bpy.types.Object) -> BIMObjectBoundaryProperties:
return obj.BIMBoundaryProperties
@classmethod
def get_assign_connection_geometry_settings(cls, obj: bpy.types.Object) -> dict[str, Any]:
from bonsai.bim.module.geometry.helper import Helper
@@ -76,7 +88,8 @@ class Boundary(bonsai.core.tool.Boundary):
@classmethod
def decorate_boundary(cls, obj: bpy.types.Object) -> None:
new = bpy.context.scene.BIMBoundaryProperties.boundaries.add()
props = cls.get_boundary_props()
new = props.boundaries.add()
new.obj = obj
obj.show_in_front = True
+1 -1
View File
@@ -135,7 +135,7 @@ class Pset(bonsai.core.tool.Pset):
return special_type
@classmethod
def import_pset_from_existing(cls, pset: ifcopenshell.entity_instance, props: bpy.types.PropertyGroup) -> None:
def import_pset_from_existing(cls, pset: ifcopenshell.entity_instance, props: PsetProperties) -> None:
pset_props = []
if pset.is_a("IfcElementQuantity"):
pset_props = pset.Quantities
+16 -10
View File
@@ -42,12 +42,17 @@ from typing import Optional, Any, Union, Literal, TYPE_CHECKING, Iterable
if TYPE_CHECKING:
import bonsai.bim.prop
from bonsai.bim.module.sequence.prop import BIMTaskTreeProperties
class Sequence(bonsai.core.tool.Sequence):
RELATED_OBJECT_TYPE = Literal["RESOURCE", "PRODUCT", "CONTROL"]
@classmethod
def get_task_tree_props(cls) -> BIMTaskTreeProperties:
return bpy.context.scene.BIMTaskTreeProperties
@classmethod
def get_work_plan_attributes(cls) -> dict[str, Any]:
import bonsai.bim.module.sequence.helper as helper
@@ -146,7 +151,8 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def load_task_tree(cls, work_schedule: ifcopenshell.entity_instance) -> None:
bpy.context.scene.BIMTaskTreeProperties.tasks.clear()
props = cls.get_task_tree_props()
props.tasks.clear()
props = bpy.context.scene.BIMWorkScheduleProperties
cls.contracted_tasks = json.loads(props.contracted_tasks)
@@ -185,7 +191,8 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def create_new_task_li(cls, related_object_id: int, level_index: int) -> None:
task = tool.Ifc.get().by_id(related_object_id)
new = bpy.context.scene.BIMTaskTreeProperties.tasks.add()
props = cls.get_task_tree_props()
new = props.tasks.add()
new.ifc_definition_id = related_object_id
new.is_expanded = related_object_id not in cls.contracted_tasks
new.level_index = level_index
@@ -199,7 +206,7 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def load_task_properties(cls, task: Optional[ifcopenshell.entity_instance] = None) -> None:
props = bpy.context.scene.BIMWorkScheduleProperties
task_props = bpy.context.scene.BIMTaskTreeProperties
task_props = cls.get_task_tree_props()
tasks_with_visual_bar = cls.get_task_bar_list()
props.is_task_update_enabled = False
@@ -281,8 +288,9 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def contract_all_tasks(cls) -> None:
props = bpy.context.scene.BIMWorkScheduleProperties
tprops = cls.get_task_tree_props()
contracted_tasks = json.loads(props.contracted_tasks)
for task_item in bpy.context.scene.BIMTaskTreeProperties.tasks:
for task_item in tprops.tasks:
if task_item.is_expanded:
contracted_tasks.append(task_item.ifc_definition_id)
props.contracted_tasks = json.dumps(contracted_tasks)
@@ -302,7 +310,7 @@ class Sequence(bonsai.core.tool.Sequence):
def disable_selecting_deleted_task(cls) -> None:
props = bpy.context.scene.BIMWorkScheduleProperties
if props.active_task_id not in [
task.ifc_definition_id for task in bpy.context.scene.BIMTaskTreeProperties.tasks
task.ifc_definition_id for task in cls.get_task_tree_props().tasks
]: # Task was deleted
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
@@ -310,9 +318,7 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def get_checked_tasks(cls) -> list[ifcopenshell.entity_instance]:
return [
tool.Ifc.get().by_id(task.ifc_definition_id)
for task in bpy.context.scene.BIMTaskTreeProperties.tasks
if task.is_selected
tool.Ifc.get().by_id(task.ifc_definition_id) for task in cls.get_task_tree_props().tasks if task.is_selected
] or []
@classmethod
@@ -486,7 +492,7 @@ class Sequence(bonsai.core.tool.Sequence):
@classmethod
def get_highlighted_task(cls) -> Union[ifcopenshell.entity_instance, None]:
tasks = bpy.context.scene.BIMTaskTreeProperties.tasks
tasks = cls.get_task_tree_props().tasks
if len(tasks) and len(tasks) > bpy.context.scene.BIMWorkScheduleProperties.active_task_index:
return tool.Ifc.get().by_id(
tasks[bpy.context.scene.BIMWorkScheduleProperties.active_task_index].ifc_definition_id
@@ -789,7 +795,7 @@ class Sequence(bonsai.core.tool.Sequence):
cls.load_task_tree(work_schedule)
cls.load_task_properties()
task_props = bpy.context.scene.BIMTaskTreeProperties
task_props = cls.get_task_tree_props()
expanded_tasks = [item.ifc_definition_id for item in task_props.tasks]
bpy.context.scene.BIMWorkScheduleProperties.active_task_index = expanded_tasks.index(task.id()) or 0
+10 -6
View File
@@ -1133,23 +1133,27 @@ class Spatial(bonsai.core.tool.Spatial):
@classmethod
def toggle_spaces_visibility_wired_and_textured(cls, spaces: list[ifcopenshell.entity_instance]) -> None:
first_obj = tool.Ifc.get_object(spaces[0])
if bpy.data.objects[first_obj.name].display_type == "TEXTURED":
assert isinstance(first_obj, bpy.types.Object)
obj: bpy.types.Object
if first_obj.display_type == "TEXTURED":
for space in spaces:
obj = tool.Ifc.get_object(space)
bpy.data.objects[obj.name].show_wire = True
bpy.data.objects[obj.name].display_type = "WIRE"
obj.show_wire = True
obj.display_type = "WIRE"
return
elif bpy.data.objects[first_obj.name].display_type == "WIRE":
elif first_obj.display_type == "WIRE":
for space in spaces:
obj = tool.Ifc.get_object(space)
bpy.data.objects[obj.name].show_wire = False
bpy.data.objects[obj.name].display_type = "TEXTURED"
obj.show_wire = False
obj.display_type = "TEXTURED"
return
@classmethod
def toggle_hide_spaces(cls, spaces: list[ifcopenshell.entity_instance]) -> None:
first_obj = tool.Ifc.get_object(spaces[0])
assert isinstance(first_obj, bpy.types.Object)
obj: bpy.types.Object
if first_obj.hide_get() == False:
for space in spaces:
obj = tool.Ifc.get_object(space)
+2 -1
View File
@@ -352,7 +352,8 @@ def i_select_the_item_name_item_in_the_list_name_list(item_name, list_name):
@when("I load a new pset template file")
def i_load_a_new_pset_template_file():
IfcStore.pset_template_path = bpy.context.scene.BIMPsetTemplateProperties.pset_template_files
props = tool.PsetTemplate.get_pset_template_props()
IfcStore.pset_template_path = props.pset_template_files
IfcStore.pset_template_file = ifcopenshell.open(IfcStore.pset_template_path)
@@ -21,6 +21,7 @@ import ifcopenshell.api.owner
import ifcopenshell.api.geometry
import ifcopenshell.guid
import ifcopenshell.util.placement
from typing import Any
def assign_port(
@@ -68,6 +69,9 @@ def assign_port(
class Usecase:
file: ifcopenshell.file
settings: dict[str, Any]
def execute(self):
if self.file.schema == "IFC2X3":
return self.execute_ifc2x3()