mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
typing
This commit is contained in:
@@ -347,8 +347,8 @@ def load_post(scene):
|
||||
|
||||
# Bonsai overlays
|
||||
georeference_props = tool.Georeference.get_georeference_props()
|
||||
aggregate_props = bpy.context.scene.BIMAggregateProperties
|
||||
nest_props = bpy.context.scene.BIMNestProperties
|
||||
aggregate_props = tool.Aggregate.get_aggregate_props()
|
||||
nest_props = tool.Nest.get_nest_props()
|
||||
model_props = tool.Model.get_model_props()
|
||||
if georeference_props.should_visualise:
|
||||
GeoreferenceDecorator.install(bpy.context)
|
||||
|
||||
@@ -20,6 +20,7 @@ import blf
|
||||
import bpy
|
||||
import gpu
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import SpaceView3D
|
||||
from bpy_extras import view3d_utils
|
||||
@@ -162,7 +163,8 @@ class AggregateDecorator:
|
||||
batch.draw(shader)
|
||||
|
||||
def draw_aggregate(self, context):
|
||||
if context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
if props.in_aggregate_mode:
|
||||
return
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
decorator_color_special = self.addon_prefs.decorator_color_special
|
||||
@@ -210,7 +212,7 @@ class AggregateDecorator:
|
||||
self.draw_batch("LINES", line_y, color, [(0, 1)])
|
||||
line_z = (location - Vector((0.0, 0.0, size)), location + Vector((0.0, 0.0, size)))
|
||||
self.draw_batch("LINES", line_z, color, [(0, 1)])
|
||||
if context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
if props.in_aggregate_mode:
|
||||
return
|
||||
parts = ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(aggregate))
|
||||
parts_objs = [tool.Ifc.get_object(p) for p in parts]
|
||||
@@ -261,7 +263,7 @@ class AggregateModeDecorator:
|
||||
return
|
||||
region = context.region
|
||||
rv3d = region.data
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
|
||||
aggregate_obj = props.editing_aggregate
|
||||
if not aggregate_obj:
|
||||
@@ -292,7 +294,7 @@ class AggregateModeDecorator:
|
||||
def draw_aggregate_empty(self, context):
|
||||
if context.mode == "EDIT_MESH":
|
||||
return
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
aggregate_obj = props.editing_aggregate
|
||||
if not aggregate_obj:
|
||||
return
|
||||
|
||||
@@ -23,6 +23,7 @@ import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
import bonsai.core.aggregate as core
|
||||
import bonsai.core.spatial
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -37,16 +38,23 @@ class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
relating_object: bpy.props.IntProperty()
|
||||
related_object: bpy.props.IntProperty()
|
||||
|
||||
if TYPE_CHECKING:
|
||||
relating_object: int
|
||||
related_object: int
|
||||
|
||||
def _execute(self, context):
|
||||
relating_obj = None
|
||||
if self.relating_object:
|
||||
relating_obj = tool.Ifc.get_object(tool.Ifc.get().by_id(self.relating_object))
|
||||
assert relating_obj
|
||||
elif self.related_object:
|
||||
aggregate = ifcopenshell.util.element.get_aggregate(tool.Ifc.get().by_id(self.related_object))
|
||||
if aggregate:
|
||||
relating_obj = tool.Ifc.get_object(aggregate)
|
||||
elif context.active_object:
|
||||
assert relating_obj
|
||||
else:
|
||||
relating_obj = context.active_object
|
||||
|
||||
if not relating_obj:
|
||||
self.report({"ERROR"}, "No relating object is provided.")
|
||||
return
|
||||
@@ -66,7 +74,7 @@ class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
relating_obj=relating_obj,
|
||||
related_obj=obj,
|
||||
)
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
if relating_obj == props.editing_aggregate and props.in_aggregate_mode:
|
||||
new_editing_obj = props.editing_objects.add()
|
||||
new_editing_obj.obj = obj
|
||||
@@ -182,7 +190,7 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj)
|
||||
|
||||
def create_aggregate(self, context, ifc_class, aggregate_name):
|
||||
def create_aggregate(self, context: bpy.types.Context, ifc_class: str, aggregate_name: str) -> bpy.types.Object:
|
||||
aggregate = bpy.data.objects.new(aggregate_name, None)
|
||||
aggregate.location = context.scene.cursor.location
|
||||
bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class=ifc_class)
|
||||
@@ -388,7 +396,7 @@ class BIM_OT_toggle_aggregate_mode_local_view(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
objs = [o.obj for o in props.editing_objects]
|
||||
if props.in_aggregate_mode:
|
||||
if context.space_data.local_view:
|
||||
|
||||
@@ -33,6 +33,7 @@ from bpy.props import (
|
||||
CollectionProperty,
|
||||
)
|
||||
from bonsai.bim.module.aggregate.decorator import AggregateDecorator, AggregateModeDecorator
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
|
||||
def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool:
|
||||
@@ -98,12 +99,22 @@ class BIMObjectAggregateProperties(PropertyGroup):
|
||||
poll=poll_related_object,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_editing: bool
|
||||
relating_object: Union[bpy.types.Object, None]
|
||||
related_object: Union[bpy.types.Object, None]
|
||||
|
||||
|
||||
class Objects(bpy.types.PropertyGroup):
|
||||
obj: PointerProperty(type=bpy.types.Object)
|
||||
previous_display_type: bpy.props.StringProperty(default="TEXTURED")
|
||||
previous_hide_select: bpy.props.BoolProperty(default=False)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
obj: Union[bpy.types.Object, None]
|
||||
previous_display_type: str
|
||||
previous_hide_select: bool
|
||||
|
||||
|
||||
class BIMAggregateProperties(PropertyGroup):
|
||||
in_aggregate_mode: BoolProperty(name="In Edit Mode", update=update_aggregate_mode_decorator)
|
||||
@@ -115,3 +126,10 @@ class BIMAggregateProperties(PropertyGroup):
|
||||
default=False,
|
||||
update=update_aggregate_decorator,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
in_aggregate_mode: bool
|
||||
editing_aggregate: Union[bpy.types.Object, None]
|
||||
editing_objects: bpy.types.bpy_prop_collection_idprop[Objects]
|
||||
not_editing_objects: bpy.types.bpy_prop_collection_idprop[Objects]
|
||||
aggregate_decorator: bool
|
||||
|
||||
@@ -49,11 +49,13 @@ class BIM_PT_aggregate(Panel):
|
||||
layout = self.layout
|
||||
row = layout.row()
|
||||
row.label(text="Aggregate Decorator")
|
||||
row.prop(context.scene.BIMAggregateProperties, "aggregate_decorator", icon="HIDE_OFF", text="")
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
row.prop(props, "aggregate_decorator", icon="HIDE_OFF", text="")
|
||||
if not AggregateData.is_loaded:
|
||||
AggregateData.load()
|
||||
|
||||
props = context.active_object.BIMObjectAggregateProperties
|
||||
assert (obj := context.active_object)
|
||||
props = tool.Aggregate.get_object_aggregate_props(obj)
|
||||
|
||||
if props.is_editing:
|
||||
row = layout.row()
|
||||
@@ -131,9 +133,8 @@ class BIM_PT_linked_aggregate(Panel):
|
||||
if not AggregateData.is_loaded:
|
||||
AggregateData.load()
|
||||
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
props = obj.BIMObjectAggregateProperties
|
||||
assert (obj := context.active_object)
|
||||
assert (element := tool.Ifc.get_entity(obj))
|
||||
row = layout.row(align=True)
|
||||
|
||||
if element.Decomposes:
|
||||
|
||||
@@ -1929,7 +1929,7 @@ class OverrideEscape(bpy.types.Operator):
|
||||
tool.Geometry.disable_item_mode()
|
||||
elif tool.Model.get_model_props().openings:
|
||||
bpy.ops.bim.hide_all_openings()
|
||||
elif context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
elif tool.Aggregate.get_aggregate_props().in_aggregate_mode:
|
||||
bpy.ops.bim.disable_aggregate_mode()
|
||||
elif active_object := context.active_object:
|
||||
if tool.Blender.Modifier.try_canceling_editing_modifier_parameters_or_path(active_object):
|
||||
@@ -1953,24 +1953,26 @@ class OverrideModeSetEdit(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
selected_objs = context.selected_objects # Purposely exclude active object
|
||||
aprops = tool.Aggregate.get_aggregate_props()
|
||||
nprops = tool.Nest.get_nest_props()
|
||||
|
||||
if self.has_aggregates(selected_objs):
|
||||
if not context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
if not aprops.in_aggregate_mode:
|
||||
bonsai.core.aggregate.enable_aggregate_mode(tool.Aggregate, context.active_object)
|
||||
return {"FINISHED"}
|
||||
|
||||
if self.has_nests(selected_objs):
|
||||
if not context.scene.BIMNestProperties.in_nest_mode:
|
||||
if not nprops.in_nest_mode:
|
||||
bonsai.core.nest.enable_nest_mode(tool.Nest, context.active_object)
|
||||
return {"FINISHED"}
|
||||
|
||||
if len(selected_objs) == 1 and context.active_object == selected_objs[0]:
|
||||
self.handle_single_object(context, context.active_object)
|
||||
elif len(selected_objs) == 0:
|
||||
if context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
if aprops.in_aggregate_mode:
|
||||
bonsai.core.aggregate.disable_aggregate_mode(tool.Aggregate)
|
||||
return {"FINISHED"}
|
||||
if context.scene.BIMNestProperties.in_nest_mode:
|
||||
if nprops.in_nest_mode:
|
||||
bonsai.core.nest.disable_nest_mode(tool.Nest)
|
||||
return {"FINISHED"}
|
||||
tool.Geometry.disable_item_mode()
|
||||
@@ -1981,9 +1983,10 @@ class OverrideModeSetEdit(bpy.types.Operator, tool.Ifc.Operator):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
props = tool.Geometry.get_geometry_props()
|
||||
pprops = tool.Project.get_project_props()
|
||||
aprops = tool.Aggregate.get_aggregate_props()
|
||||
if obj == props.representation_obj:
|
||||
self.report({"ERROR"}, f"Element '{obj.name}' is in item mode and cannot be edited directly")
|
||||
elif obj in [o.obj for o in context.scene.BIMAggregateProperties.not_editing_objects]:
|
||||
elif obj in [o.obj for o in aprops.not_editing_objects]:
|
||||
obj.select_set(False)
|
||||
self.report(
|
||||
{"ERROR"}, f"Element '{obj.name}' does not belong to this aggregate and cannot be edited directly"
|
||||
@@ -2099,7 +2102,8 @@ class OverrideModeSetEdit(bpy.types.Operator, tool.Ifc.Operator):
|
||||
continue
|
||||
aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||
parts = ifcopenshell.util.element.get_parts(element)
|
||||
if (aggregate or parts) and not bpy.context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
if (aggregate or parts) and not props.in_aggregate_mode:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -2111,7 +2115,8 @@ class OverrideModeSetEdit(bpy.types.Operator, tool.Ifc.Operator):
|
||||
continue
|
||||
nest = ifcopenshell.util.element.get_nest(element)
|
||||
components = ifcopenshell.util.element.get_components(element)
|
||||
if (nest or components) and not bpy.context.scene.BIMNestProperties.in_nest_mode:
|
||||
props = tool.Nest.get_nest_props()
|
||||
if (nest or components) and not props.in_nest_mode:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -3270,7 +3275,7 @@ class OverrideMove(bpy.types.Operator):
|
||||
self.new_active_obj = obj
|
||||
|
||||
# Get aggregates
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
not_editing_objs = [o.obj for o in props.not_editing_objects]
|
||||
aggregates_to_move = []
|
||||
for obj in context.selected_objects:
|
||||
@@ -3305,7 +3310,7 @@ class OverrideMove(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
# Get nests
|
||||
props = context.scene.BIMNestProperties
|
||||
props = tool.Nest.get_nest_props()
|
||||
not_editing_objs = [o.obj for o in props.not_editing_objects]
|
||||
nests_to_move = []
|
||||
for obj in context.selected_objects:
|
||||
|
||||
@@ -717,12 +717,14 @@ class EditObjectUI:
|
||||
AuthoringData.load(ifc_element_type)
|
||||
|
||||
if context.region.type == "TOOL_HEADER":
|
||||
if context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
aprops = tool.Aggregate.get_aggregate_props()
|
||||
if aprops.in_aggregate_mode:
|
||||
layout.label(text=f"Aggregate Mode", icon="EMPTY_AXIS")
|
||||
row = cls.layout.row(align=True)
|
||||
op = row.operator("bim.disable_aggregate_mode", text="", icon="X")
|
||||
op = row.operator("bim.toggle_aggregate_mode_local_view", text="", icon="ZOOM_SELECTED")
|
||||
if context.scene.BIMNestProperties.in_nest_mode:
|
||||
nprops = tool.Nest.get_nest_props()
|
||||
if nprops.in_nest_mode:
|
||||
layout.label(text=f"Nest Mode", icon="EMPTY_AXIS")
|
||||
row = cls.layout.row(align=True)
|
||||
op = row.operator("bim.disable_nest_mode", text="", icon="X")
|
||||
|
||||
@@ -20,6 +20,7 @@ import blf
|
||||
import bpy
|
||||
import gpu
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import SpaceView3D
|
||||
from bpy_extras import view3d_utils
|
||||
@@ -162,8 +163,9 @@ class NestDecorator:
|
||||
shader.uniform_float("color", color)
|
||||
batch.draw(shader)
|
||||
|
||||
def draw_nest(self, context):
|
||||
if context.scene.BIMNestProperties.in_nest_mode:
|
||||
def draw_nest(self, context: bpy.types.Context) -> None:
|
||||
props = tool.Nest.get_nest_props()
|
||||
if props.in_nest_mode:
|
||||
return
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
decorator_color_special = self.addon_prefs.decorator_color_special
|
||||
@@ -262,7 +264,7 @@ class NestModeDecorator:
|
||||
return
|
||||
region = context.region
|
||||
rv3d = region.data
|
||||
props = context.scene.BIMNestProperties
|
||||
props = tool.Nest.get_nest_props()
|
||||
|
||||
aggregate_obj = props.editing_nest
|
||||
if not aggregate_obj:
|
||||
@@ -291,7 +293,7 @@ class NestModeDecorator:
|
||||
def draw_nest_empty(self, context):
|
||||
if context.mode == "EDIT_MESH":
|
||||
return
|
||||
props = context.scene.BIMNestProperties
|
||||
props = tool.Nest.get_nest_props()
|
||||
nest_obj = props.editing_nest
|
||||
if not nest_obj:
|
||||
return
|
||||
|
||||
@@ -158,7 +158,7 @@ class BIM_OT_toggle_nest_mode_local_view(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMNestProperties
|
||||
props = tool.Nest.get_nest_props()
|
||||
objs = [o.obj for o in props.editing_objects]
|
||||
if props.in_nest_mode:
|
||||
if context.space_data.local_view:
|
||||
|
||||
@@ -32,10 +32,11 @@ from bpy.props import (
|
||||
CollectionProperty,
|
||||
)
|
||||
from bonsai.bim.module.nest.decorator import NestDecorator, NestModeDecorator
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
|
||||
def update_relating_object(self, context):
|
||||
def message(self, context):
|
||||
def update_relating_object(self: "BIMObjectNestProperties", context: bpy.types.Context) -> None:
|
||||
def message(self, context: bpy.types.Context) -> None:
|
||||
self.layout.label(text="Please select a valid Ifc Element")
|
||||
|
||||
if self.relating_object is None:
|
||||
@@ -49,15 +50,19 @@ class BIMObjectNestProperties(PropertyGroup):
|
||||
is_editing: BoolProperty(name="Is Editing")
|
||||
relating_object: PointerProperty(name="Nest Host", type=bpy.types.Object, update=update_relating_object)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_editing: bool
|
||||
relating_object: bpy.types.Object
|
||||
|
||||
def update_nest_decorator(self, context):
|
||||
|
||||
def update_nest_decorator(self: "BIMNestProperties", context: bpy.types.Context) -> None:
|
||||
if self.nest_decorator:
|
||||
NestDecorator.install(bpy.context)
|
||||
else:
|
||||
NestDecorator.uninstall()
|
||||
|
||||
|
||||
def update_nest_mode_decorator(self, context):
|
||||
def update_nest_mode_decorator(self: "BIMNestProperties", context: bpy.types.Context) -> None:
|
||||
if self.in_nest_mode:
|
||||
NestModeDecorator.install(bpy.context)
|
||||
else:
|
||||
@@ -68,6 +73,10 @@ class Objects(bpy.types.PropertyGroup):
|
||||
obj: PointerProperty(type=bpy.types.Object)
|
||||
previous_display_type: bpy.props.StringProperty(default="TEXTURED")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
obj: Union[bpy.types.Object, None]
|
||||
previous_display_type: str
|
||||
|
||||
|
||||
class BIMNestProperties(PropertyGroup):
|
||||
in_nest_mode: BoolProperty(name="In Edit Mode", update=update_nest_mode_decorator)
|
||||
@@ -79,3 +88,10 @@ class BIMNestProperties(PropertyGroup):
|
||||
default=False,
|
||||
update=update_nest_decorator,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
in_nest_mode: bool
|
||||
editing_nest: Union[bpy.types.Object, None]
|
||||
editing_objects: bpy.types.bpy_prop_collection_idprop[Objects]
|
||||
not_editing_objects: bpy.types.bpy_prop_collection_idprop[Objects]
|
||||
nest_decorator: bool
|
||||
|
||||
@@ -48,7 +48,8 @@ class BIM_PT_nest(Panel):
|
||||
if not NestData.is_loaded:
|
||||
NestData.load()
|
||||
|
||||
props = context.active_object.BIMObjectNestProperties
|
||||
assert (obj := context.active_object)
|
||||
props = tool.Nest.get_object_nest_props(obj)
|
||||
|
||||
if props.is_editing:
|
||||
row = layout.row(align=True)
|
||||
|
||||
@@ -35,6 +35,7 @@ import bonsai.bim.module.root.prop as root_prop
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.helper import get_enum_items, prop_with_search
|
||||
from mathutils import Vector
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
class EnableReassignClass(bpy.types.Operator):
|
||||
@@ -182,6 +183,15 @@ class AssignClass(bpy.types.Operator, tool.Ifc.Operator):
|
||||
should_add_representation: bpy.props.BoolProperty(default=True)
|
||||
ifc_representation_class: bpy.props.StringProperty()
|
||||
|
||||
if TYPE_CHECKING:
|
||||
obj: str
|
||||
ifc_class: str
|
||||
predefined_type: str
|
||||
userdefined_type: str
|
||||
context_id: int
|
||||
should_add_representation: bool
|
||||
ifc_representation_class: str
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Root.get_root_props()
|
||||
objects: list[bpy.types.Object] = []
|
||||
|
||||
@@ -1262,8 +1262,8 @@ class BIM_PT_decorators_overlay(Panel):
|
||||
overlay = view.overlay
|
||||
|
||||
georeference_props = tool.Georeference.get_georeference_props()
|
||||
aggregate_props = bpy.context.scene.BIMAggregateProperties
|
||||
nest_props = bpy.context.scene.BIMNestProperties
|
||||
aggregate_props = tool.Aggregate.get_aggregate_props()
|
||||
nest_props = tool.Nest.get_nest_props()
|
||||
model_props = tool.Model.get_model_props()
|
||||
display_all = overlay.show_overlays
|
||||
|
||||
|
||||
@@ -25,15 +25,21 @@ if TYPE_CHECKING:
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
def enable_editing_nest(nest, obj=None):
|
||||
def enable_editing_nest(nest: tool.Nest, obj: bpy.types.Object) -> None:
|
||||
nest.enable_editing(obj)
|
||||
|
||||
|
||||
def disable_editing_nest(nest, obj=None):
|
||||
def disable_editing_nest(nest: tool.Nest, obj: bpy.types.Object) -> None:
|
||||
nest.disable_editing(obj)
|
||||
|
||||
|
||||
def assign_object(ifc, nest, collector, relating_obj=None, related_obj=None):
|
||||
def assign_object(
|
||||
ifc: tool.Ifc,
|
||||
nest: tool.Nest,
|
||||
collector: tool.Collector,
|
||||
relating_obj: bpy.types.Object,
|
||||
related_obj: bpy.types.Object,
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
if not nest.can_nest(relating_obj, related_obj):
|
||||
return
|
||||
rel = ifc.run(
|
||||
@@ -47,14 +53,22 @@ def assign_object(ifc, nest, collector, relating_obj=None, related_obj=None):
|
||||
return rel
|
||||
|
||||
|
||||
def unassign_object(ifc, nest, collector, relating_obj=None, related_obj=None):
|
||||
def unassign_object(
|
||||
ifc: tool.Ifc,
|
||||
nest: tool.Nest,
|
||||
collector: tool.Collector,
|
||||
relating_obj: bpy.types.Object,
|
||||
related_obj: bpy.types.Object,
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
related_element = ifc.get_entity(related_obj)
|
||||
assert related_element
|
||||
container = nest.get_container(related_element)
|
||||
# TODO: this branch is never used?
|
||||
if not relating_obj:
|
||||
relating_element = nest.get_relating_object(related_element)
|
||||
if related_element:
|
||||
relating_obj = ifc.get_object(relating_element)
|
||||
if relating_obj:
|
||||
else:
|
||||
ifc.run("nest.unassign_object", related_objects=[related_element])
|
||||
if container:
|
||||
ifc.run("spatial.assign_container", products=[related_element], relating_structure=container)
|
||||
@@ -62,21 +76,28 @@ def unassign_object(ifc, nest, collector, relating_obj=None, related_obj=None):
|
||||
collector.assign(related_obj)
|
||||
|
||||
|
||||
def add_part_to_object(ifc, nest, collector, blender, obj, part_class, part_name=None):
|
||||
def add_part_to_object(
|
||||
ifc: tool.Ifc,
|
||||
nest: tool.Nest,
|
||||
collector: tool.Collector,
|
||||
blender: tool.Blender,
|
||||
obj: bpy.types.Object,
|
||||
part_class: str,
|
||||
part_name: str,
|
||||
) -> None:
|
||||
part_obj = blender.create_ifc_object(ifc_class=part_class, name=part_name)
|
||||
assign_object(ifc, nest, collector, relating_obj=obj, related_obj=part_obj)
|
||||
blender.set_active_object(obj)
|
||||
|
||||
|
||||
def enable_nest_mode(
|
||||
nest: tool.Nest,
|
||||
obj: bpy.types.Object,
|
||||
):
|
||||
) -> None:
|
||||
if nest.get_nest_mode():
|
||||
disable_nest_mode(nest)
|
||||
|
||||
nest.enable_nest_mode(obj)
|
||||
|
||||
|
||||
def disable_nest_mode(nest: tool.Nest):
|
||||
def disable_nest_mode(nest: tool.Nest) -> None:
|
||||
nest.disable_nest_mode()
|
||||
|
||||
@@ -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 bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
from typing import Union
|
||||
from typing import Union, TYPE_CHECKING, Literal
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.aggregate.prop import BIMAggregateProperties, BIMObjectAggregateProperties
|
||||
|
||||
|
||||
class Aggregate(bonsai.core.tool.Aggregate):
|
||||
@classmethod
|
||||
def get_aggregate_props(cls) -> BIMAggregateProperties:
|
||||
return bpy.context.scene.BIMAggregateProperties
|
||||
|
||||
@classmethod
|
||||
def get_object_aggregate_props(cls, obj: bpy.types.Object) -> BIMObjectAggregateProperties:
|
||||
return obj.BIMObjectAggregateProperties
|
||||
|
||||
@classmethod
|
||||
def can_aggregate(cls, relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool:
|
||||
relating_object = tool.Ifc.get_entity(relating_obj)
|
||||
@@ -56,11 +68,13 @@ class Aggregate(bonsai.core.tool.Aggregate):
|
||||
|
||||
@classmethod
|
||||
def disable_editing(cls, obj: bpy.types.Object) -> None:
|
||||
obj.BIMObjectAggregateProperties.is_editing = False
|
||||
props = cls.get_object_aggregate_props(obj)
|
||||
props.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def enable_editing(cls, obj: bpy.types.Object) -> None:
|
||||
obj.BIMObjectAggregateProperties.is_editing = True
|
||||
props = cls.get_object_aggregate_props(obj)
|
||||
props.is_editing = True
|
||||
|
||||
@classmethod
|
||||
def get_container(cls, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||
@@ -86,13 +100,14 @@ class Aggregate(bonsai.core.tool.Aggregate):
|
||||
return parts
|
||||
|
||||
@classmethod
|
||||
def get_aggregate_mode(cls):
|
||||
return bpy.context.scene.BIMAggregateProperties.in_aggregate_mode
|
||||
def get_aggregate_mode(cls) -> bool:
|
||||
props = cls.get_aggregate_props()
|
||||
return props.in_aggregate_mode
|
||||
|
||||
@classmethod
|
||||
def enable_aggregate_mode(cls, active_object: bpy.types.Object):
|
||||
def enable_aggregate_mode(cls, active_object: bpy.types.Object) -> set[Literal["FINISHED"]]:
|
||||
context = bpy.context
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = cls.get_aggregate_props()
|
||||
|
||||
element = tool.Ifc.get_entity(active_object)
|
||||
if not element:
|
||||
@@ -131,7 +146,7 @@ class Aggregate(bonsai.core.tool.Aggregate):
|
||||
@classmethod
|
||||
def disable_aggregate_mode(cls):
|
||||
context = bpy.context
|
||||
props = context.scene.BIMAggregateProperties
|
||||
props = cls.get_aggregate_props()
|
||||
for obj_prop in props.not_editing_objects:
|
||||
obj = obj_prop.obj
|
||||
if not obj:
|
||||
|
||||
@@ -16,13 +16,26 @@
|
||||
# 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 bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
import ifcopenshell.util.element
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.nest.prop import BIMNestProperties, BIMObjectNestProperties
|
||||
|
||||
|
||||
class Nest(bonsai.core.tool.Nest):
|
||||
@classmethod
|
||||
def get_nest_props(cls) -> BIMNestProperties:
|
||||
return bpy.context.scene.BIMNestProperties
|
||||
|
||||
@classmethod
|
||||
def get_object_nest_props(cls, obj: bpy.types.Object) -> BIMObjectNestProperties:
|
||||
return obj.BIMObjectNestProperties
|
||||
|
||||
@classmethod
|
||||
def can_nest(cls, relating_obj, related_obj):
|
||||
relating_object = tool.Ifc.get_entity(relating_obj)
|
||||
@@ -34,19 +47,23 @@ class Nest(bonsai.core.tool.Nest):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def disable_editing(cls, obj):
|
||||
obj.BIMObjectNestProperties.is_editing = False
|
||||
def disable_editing(cls, obj: bpy.types.Object) -> None:
|
||||
props = cls.get_object_nest_props(obj)
|
||||
props.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def enable_editing(cls, obj):
|
||||
obj.BIMObjectNestProperties.is_editing = True
|
||||
def enable_editing(cls, obj: bpy.types.Object) -> None:
|
||||
props = cls.get_object_nest_props(obj)
|
||||
props.is_editing = True
|
||||
|
||||
@classmethod
|
||||
def get_container(cls, element):
|
||||
def get_container(cls, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||
return ifcopenshell.util.element.get_container(element)
|
||||
|
||||
@classmethod
|
||||
def get_relating_object(cls, related_element):
|
||||
def get_relating_object(
|
||||
cls, related_element: ifcopenshell.entity_instance
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
return ifcopenshell.util.element.get_nest(related_element)
|
||||
|
||||
@classmethod
|
||||
@@ -61,13 +78,14 @@ class Nest(bonsai.core.tool.Nest):
|
||||
return components
|
||||
|
||||
@classmethod
|
||||
def get_nest_mode(cls):
|
||||
return bpy.context.scene.BIMNestProperties.in_nest_mode
|
||||
def get_nest_mode(cls) -> bool:
|
||||
props = cls.get_nest_props()
|
||||
return props.in_nest_mode
|
||||
|
||||
@classmethod
|
||||
def enable_nest_mode(cls, active_object: bpy.types.Object):
|
||||
context = bpy.context
|
||||
props = context.scene.BIMNestProperties
|
||||
props = cls.get_nest_props()
|
||||
|
||||
element = tool.Ifc.get_entity(active_object)
|
||||
if not element:
|
||||
|
||||
@@ -238,13 +238,13 @@ class Root(bonsai.core.tool.Root):
|
||||
|
||||
@classmethod
|
||||
def is_in_aggregate_mode(cls, element: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
props = bpy.context.scene.BIMAggregateProperties
|
||||
props = tool.Aggregate.get_aggregate_props()
|
||||
if props.editing_aggregate and props.in_aggregate_mode:
|
||||
return tool.Ifc.get_entity(props.editing_aggregate)
|
||||
|
||||
@classmethod
|
||||
def is_in_nest_mode(cls, element: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
props = bpy.context.scene.BIMNestProperties
|
||||
props = tool.Nest.get_nest_props()
|
||||
if props.editing_nest and props.in_nest_mode:
|
||||
return tool.Ifc.get_entity(props.editing_nest)
|
||||
|
||||
|
||||
@@ -122,14 +122,16 @@ class TestDisableEditing(NewFile):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
subject.enable_editing(obj)
|
||||
subject.disable_editing(obj)
|
||||
assert obj.BIMObjectAggregateProperties.is_editing is False
|
||||
props = tool.Aggregate.get_object_aggregate_props(obj)
|
||||
assert props.is_editing is False
|
||||
|
||||
|
||||
class TestEnableEditing(NewFile):
|
||||
def test_run(self):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
subject.enable_editing(obj)
|
||||
assert obj.BIMObjectAggregateProperties.is_editing is True
|
||||
props = tool.Aggregate.get_object_aggregate_props(obj)
|
||||
assert props.is_editing is True
|
||||
|
||||
|
||||
class TestGetContainer(NewFile):
|
||||
|
||||
@@ -54,14 +54,16 @@ class TestDisableEditing(NewFile):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
subject.enable_editing(obj)
|
||||
subject.disable_editing(obj)
|
||||
assert obj.BIMObjectNestProperties.is_editing is False
|
||||
props = tool.Nest.get_object_nest_props(obj)
|
||||
assert props.is_editing is False
|
||||
|
||||
|
||||
class TestEnableEditing(NewFile):
|
||||
def test_run(self):
|
||||
obj = bpy.data.objects.new("Object", None)
|
||||
subject.enable_editing(obj)
|
||||
assert obj.BIMObjectNestProperties.is_editing is True
|
||||
props = tool.Nest.get_object_nest_props(obj)
|
||||
assert props.is_editing is True
|
||||
|
||||
|
||||
class TestGetContainer(NewFile):
|
||||
|
||||
@@ -112,15 +112,15 @@ class Usecase:
|
||||
ifc_vertices: list[ifcopenshell.entity_instance]
|
||||
coordinate_offset: Union[npt.NDArray[np.float64], None]
|
||||
geometry: Union[bpy.types.Mesh, bpy.types.Curve]
|
||||
blender_object: bpy.types.Object
|
||||
|
||||
def execute(self) -> Union[ifcopenshell.entity_instance, None]:
|
||||
self.is_manifold = None
|
||||
self.coordinate_offset = self.settings["coordinate_offset"]
|
||||
self.geometry = self.settings["geometry"]
|
||||
if (
|
||||
isinstance(self.settings["geometry"], bpy.types.Mesh)
|
||||
and self.settings["geometry"] == self.settings["blender_object"].data
|
||||
):
|
||||
self.blender_object = self.settings["blender_object"]
|
||||
|
||||
if isinstance(self.geometry, bpy.types.Mesh) and self.geometry == self.blender_object.data:
|
||||
self.evaluate_geometry()
|
||||
if self.settings["unit_scale"] is None:
|
||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||
@@ -147,11 +147,11 @@ class Usecase:
|
||||
return any([abs((tM @ v.co).z) > threshold for v in face.verts])
|
||||
|
||||
def evaluate_geometry(self) -> None:
|
||||
for modifier in self.settings["blender_object"].modifiers:
|
||||
for modifier in self.blender_object.modifiers:
|
||||
if modifier.type == "BOOLEAN":
|
||||
modifier.show_viewport = False
|
||||
|
||||
mesh = self.settings["blender_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||
mesh = self.blender_object.evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh)
|
||||
|
||||
@@ -173,7 +173,7 @@ class Usecase:
|
||||
|
||||
self.settings["geometry"] = mesh
|
||||
|
||||
for modifier in self.settings["blender_object"].modifiers:
|
||||
for modifier in self.blender_object.modifiers:
|
||||
if modifier.type == "BOOLEAN":
|
||||
modifier.show_viewport = True
|
||||
|
||||
@@ -540,7 +540,7 @@ class Usecase:
|
||||
|
||||
# create dummy object that will have more detailed curves
|
||||
# since now we do not really support splines curves natively
|
||||
obj = self.settings["blender_object"]
|
||||
obj = self.blender_object
|
||||
dummy = bpy.data.objects.new("Dummy", obj.data.copy())
|
||||
bpy.context.scene.collection.objects.link(dummy)
|
||||
tool.Blender.select_and_activate_single_object(bpy.context, dummy)
|
||||
@@ -752,7 +752,7 @@ class Usecase:
|
||||
profile_def,
|
||||
position,
|
||||
self.file.createIfcDirection((0.0, 0.0, 1.0)),
|
||||
self.convert_si_to_unit(self.settings["blender_object"].dimensions[2]),
|
||||
self.convert_si_to_unit(self.blender_object.dimensions[2]),
|
||||
)
|
||||
return self.file.createIfcShapeRepresentation(
|
||||
self.settings["context"],
|
||||
@@ -952,7 +952,7 @@ class Usecase:
|
||||
)
|
||||
|
||||
def create_box_representation(self) -> ifcopenshell.entity_instance:
|
||||
obj = self.settings["blender_object"]
|
||||
obj = self.blender_object
|
||||
bounding_box = self.file.createIfcBoundingBox(
|
||||
self.create_cartesian_point(obj.bound_box[0][0], obj.bound_box[0][1], obj.bound_box[0][2]),
|
||||
self.convert_si_to_unit(obj.dimensions[0]),
|
||||
|
||||
Reference in New Issue
Block a user