mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Added tool.Blender.Modifier.has_mirrored_type and set_mirrored_type.
This commit is contained in:
committed by
Ryan Schultz
parent
9f091b7a78
commit
ba4a94dfea
@@ -783,6 +783,7 @@ class FlipFill(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tool.Geometry.reload_representation(filled_object)
|
||||
|
||||
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -682,136 +682,6 @@ class MirrorElements(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
obj.matrix_world = newmat
|
||||
|
||||
class TrueMirrorElements(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.mirror_geometry"
|
||||
bl_label = "Mirror Element Geometry"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Mirrors the selected objects by mirroring their representation (or their types representation)"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.selected_objects
|
||||
|
||||
def _execute(self, context):
|
||||
for obj in context.selected_objects:
|
||||
self.change_obj_swing_direction(obj)
|
||||
return { "FINISHED" }
|
||||
|
||||
def change_obj_swing_direction(self, obj):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
type_element = ifcopenshell.util.element.get_type(element)
|
||||
|
||||
active_context = tool.Geometry.get_active_representation_context(obj)
|
||||
|
||||
if type_element and element.id() != type_element.id():
|
||||
# obj has a type, use / create inverted type and assign it
|
||||
self.assign_inverted_type(element)
|
||||
else:
|
||||
# invert representation of entity directly
|
||||
self.invert_representation(element)
|
||||
|
||||
# bonsai does not automatically switch to the representation that should be active in the given context
|
||||
# when switching to a type that was previously viewed in another context (e.g. plan view),
|
||||
# the wrong representation will be used.
|
||||
bonsai.core.geometry.switch_representation(
|
||||
tool.Ifc,
|
||||
tool.Geometry,
|
||||
obj=obj,
|
||||
representation=ifcopenshell.util.representation.get_representation(element, active_context),
|
||||
should_reload=False,
|
||||
is_global=False,
|
||||
should_sync_changes_first=False,
|
||||
)
|
||||
|
||||
def invert_general_object(self, element):
|
||||
if element.is_a("IfcProduct"):
|
||||
if not element.Representation:
|
||||
return
|
||||
|
||||
for representation in element.Representation.Representations:
|
||||
for item in representation.Items:
|
||||
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
|
||||
builder.mirror(item, (1, 0), create_copy=False)
|
||||
elif element.is_a("IfcTypeProduct"):
|
||||
for representation_map in element.RepresentationMaps:
|
||||
for item in representation_map.MappedRepresentation.Items:
|
||||
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
|
||||
builder.mirror(item, (1, 0), create_copy=False)
|
||||
|
||||
tool.Geometry.reload_representation(tool.Ifc.get_object(element))
|
||||
|
||||
def invert_door_swing(self, element):
|
||||
obj = tool.Ifc.get_object(element)
|
||||
|
||||
pset_data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Door", "Data"))
|
||||
|
||||
if "LEFT" in pset_data["door_type"]:
|
||||
pset_data["door_type"] = pset_data["door_type"].replace("LEFT", "RIGHT")
|
||||
elif "RIGHT" in pset_data["door_type"]:
|
||||
pset_data["door_type"] = pset_data["door_type"].replace("RIGHT", "LEFT")
|
||||
|
||||
pset = tool.Pset.get_element_pset(element, "BBIM_Door")
|
||||
pset_data_str = tool.Ifc.get().createIfcText(json.dumps(pset_data, default=list))
|
||||
ifcopenshell.api.pset.edit_pset(tool.Ifc.get(), pset=pset, properties={"Data": pset_data_str})
|
||||
|
||||
pset_data.update(pset_data.pop("lining_properties"))
|
||||
pset_data.update(pset_data.pop("panel_properties"))
|
||||
pset_data.update(tool.Model.get_constituents_props_data(element))
|
||||
|
||||
# we need this workaround because set_props_kwargs_from_ifc_data will
|
||||
# "update" the mesh of the active object, which will switch its representation
|
||||
prev_active = bpy.context.view_layer.objects.active
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
|
||||
props = tool.Model.get_door_props(obj)
|
||||
props.set_props_kwargs_from_ifc_data(pset_data)
|
||||
|
||||
bpy.context.view_layer.objects.active = prev_active
|
||||
|
||||
# regenerate door geometry
|
||||
update_door_modifier_representation(obj)
|
||||
|
||||
tool.Model.mark_thumbnail_for_update(element)
|
||||
|
||||
def invert_representation(self, element):
|
||||
if ifcopenshell.util.element.get_pset(element, "BBIM_Door", "Data"):
|
||||
self.invert_door_swing(element)
|
||||
else:
|
||||
self.invert_general_object(element)
|
||||
|
||||
def get_inverted_type(self, type_element):
|
||||
inverted_pset = ifcopenshell.util.element.get_pset(type_element, "BBIM_InvertedSwingType", "Data")
|
||||
if not inverted_pset:
|
||||
return None
|
||||
|
||||
data = json.loads(inverted_pset)
|
||||
if "inverted_swing_type" in data:
|
||||
return tool.Ifc.get_entity_by_id(int(data["inverted_swing_type"]))
|
||||
return None
|
||||
|
||||
def set_inverted_type(self, type_element, inverted_type_element):
|
||||
inverted_pset = tool.Pset.get_element_pset(type_element, "BBIM_InvertedSwingType")
|
||||
if not inverted_pset:
|
||||
inverted_pset = ifcopenshell.api.pset.add_pset(tool.Ifc.get(), type_element, "BBIM_InvertedSwingType")
|
||||
|
||||
ifcopenshell.api.pset.edit_pset(tool.Ifc.get(), inverted_pset, "BBIM_InvertedSwingType", { "Data": json.dumps({ "inverted_swing_type": inverted_type_element.id() }) })
|
||||
|
||||
def assign_inverted_type(self, element):
|
||||
type_element = ifcopenshell.util.element.get_type(element)
|
||||
|
||||
inverted_type = self.get_inverted_type(type_element)
|
||||
if not inverted_type:
|
||||
old_to_new, _ = tool.Geometry.duplicate_ifc_objects([ tool.Ifc.get_object(type_element) ])
|
||||
inverted_type = old_to_new[type_element][0]
|
||||
self.invert_representation(inverted_type)
|
||||
self.set_inverted_type(inverted_type, type_element)
|
||||
self.set_inverted_type(type_element, inverted_type)
|
||||
inverted_type.Name = f"{inverted_type.Name}.Mirror"
|
||||
|
||||
bonsai.core.type.assign_type(tool.Ifc, tool.Type, element, inverted_type)
|
||||
|
||||
|
||||
class TrueMirrorElements(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.mirror_geometry"
|
||||
|
||||
@@ -1093,13 +1093,6 @@ class EditObjectUI:
|
||||
def draw_flip(cls, ui_context, layout) -> None:
|
||||
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else layout
|
||||
add_layout_hotkey_operator(row, "Flip", "S_F", bpy.ops.bim.flip_object.__doc__, ui_context)
|
||||
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else layout
|
||||
add_layout_hotkey_operator(row, "Mirror Geometry", "C_F", bpy.ops.bim.mirror_geometry.__doc__, ui_context)
|
||||
|
||||
@classmethod
|
||||
def draw_mirror_geometry(cls, ui_context, layout) -> None:
|
||||
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else layout
|
||||
add_layout_hotkey_operator(row, "Mirror Geometry", "C_F", bpy.ops.bim.mirror_geometry.__doc__, ui_context)
|
||||
|
||||
@classmethod
|
||||
def draw_mirror_geometry(cls, ui_context, layout) -> None:
|
||||
@@ -1308,7 +1301,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def hotkey_C_F(self):
|
||||
if not bpy.context.selected_objects:
|
||||
return
|
||||
bpy.ops.bim.mirror_geometry()
|
||||
bpy.ops.bim.mirror_geometry(keep_original=getattr(self, "shift", False))
|
||||
|
||||
def hotkey_S_G(self):
|
||||
obj = bpy.context.active_object
|
||||
|
||||
Reference in New Issue
Block a user