This commit is contained in:
Andrej730
2025-04-09 11:31:25 +05:00
parent 3052c6e578
commit cf1f74e260
20 changed files with 204 additions and 81 deletions
+2 -2
View File
@@ -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
+6 -5
View File
@@ -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:
+20 -4
View File
@@ -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
+2 -1
View File
@@ -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] = []
+2 -2
View File
@@ -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
+30 -9
View File
@@ -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()
+23 -8
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 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:
+27 -9
View File
@@ -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:
+2 -2
View File
@@ -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)
+4 -2
View File
@@ -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):
+4 -2
View File
@@ -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]),