mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Merge pull request #5930 from Gorgious56/improve_modifiers
Modifiers QOL
This commit is contained in:
@@ -78,9 +78,6 @@ class ViewportData:
|
||||
modes.append(edit_mode)
|
||||
elif element.is_a("IfcGridAxis"):
|
||||
modes.append(edit_mode)
|
||||
elif tool.Blender.Modifier.is_editing_parameters(obj):
|
||||
# This should go BEFORE the modifiers
|
||||
pass
|
||||
elif tool.Blender.Modifier.is_roof(element):
|
||||
modes.append(edit_mode)
|
||||
elif tool.Blender.Modifier.is_railing(element):
|
||||
|
||||
@@ -1858,8 +1858,9 @@ class OverrideEscape(bpy.types.Operator):
|
||||
bpy.ops.bim.hide_all_openings()
|
||||
elif context.scene.BIMAggregateProperties.in_aggregate_mode:
|
||||
bpy.ops.bim.disable_aggregate_mode()
|
||||
elif context.active_object and context.active_object.BIMRailingProperties.is_editing_path:
|
||||
bpy.ops.bim.cancel_editing_railing_path()
|
||||
elif active_object:=context.active_object:
|
||||
if tool.Blender.Modifier.try_canceling_editing_modifier_parameters_or_path(active_object):
|
||||
pass
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -1921,13 +1922,8 @@ class OverrideModeSetEdit(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.ops.bim.enable_editing_boundary_geometry()
|
||||
elif element.is_a("IfcGridAxis"):
|
||||
self.enable_edit_mode(context)
|
||||
elif tool.Blender.Modifier.is_editing_parameters(obj):
|
||||
# This should go BEFORE the modifiers
|
||||
self.report({"INFO"}, "Can't edit while modifier parameters are being modified")
|
||||
elif tool.Blender.Modifier.is_roof(element):
|
||||
bpy.ops.bim.enable_editing_roof_path()
|
||||
elif tool.Blender.Modifier.is_railing(element):
|
||||
bpy.ops.bim.enable_editing_railing_path()
|
||||
elif tool.Blender.Modifier.try_applying_edit_mode(obj, element):
|
||||
pass
|
||||
else:
|
||||
bpy.ops.bim.import_representation_items()
|
||||
elif tool.Geometry.is_representation_item(obj):
|
||||
|
||||
@@ -186,6 +186,7 @@ classes = (
|
||||
roof.BIM_OT_add_roof,
|
||||
roof.AddRoof,
|
||||
roof.CancelEditingRoof,
|
||||
roof.CopyRoofParameters,
|
||||
roof.FinishEditingRoof,
|
||||
roof.EnableEditingRoof,
|
||||
roof.CancelEditingRoofPath,
|
||||
|
||||
@@ -569,6 +569,7 @@ class RoofData:
|
||||
if not cls.data["pset_data"]:
|
||||
return
|
||||
cls.data["general_params"] = cls.general_params()
|
||||
cls.data["path_data"] = cls.path_data()
|
||||
|
||||
@classmethod
|
||||
def pset_data(cls):
|
||||
@@ -589,6 +590,10 @@ class RoofData:
|
||||
general_params[prop_readable_name] = prop_value
|
||||
return general_params
|
||||
|
||||
@classmethod
|
||||
def path_data(cls):
|
||||
return cls.data["pset_data"]["data_dict"]["path_data"]
|
||||
|
||||
|
||||
class ItemData:
|
||||
data = {}
|
||||
|
||||
@@ -438,7 +438,7 @@ def update_roof_modifier_bmesh(obj: bpy.types.Object) -> None:
|
||||
# NOTE: using Data since bmesh update will hapen very often
|
||||
if not RoofData.is_loaded:
|
||||
RoofData.load()
|
||||
path_data = RoofData.data["pset_data"]["data_dict"]["path_data"]
|
||||
path_data = RoofData.data["path_data"]
|
||||
angle_layer_data = path_data.get("gable_roof_angles", None)
|
||||
separate_verts_data = path_data.get("gable_roof_separate_verts", None)
|
||||
|
||||
@@ -739,6 +739,41 @@ class CancelEditingRoofPath(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return cancel_editing_roof_path(context)
|
||||
|
||||
|
||||
class CopyRoofParameters(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.copy_roof_parameters"
|
||||
bl_label = "Copy Roof Parameters from Active to Selected"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.active_object and len(context.selected_objects) > 1
|
||||
|
||||
def _execute(self, context):
|
||||
source_obj = context.active_object
|
||||
source_props = source_obj.BIMRoofProperties
|
||||
data = source_props.get_general_kwargs(convert_to_project_units=True)
|
||||
|
||||
for target_obj in context.selected_objects:
|
||||
if target_obj == source_obj:
|
||||
continue
|
||||
context.view_layer.objects.active = target_obj
|
||||
RoofData.load()
|
||||
if not "path_data" in RoofData.data:
|
||||
continue
|
||||
data["path_data"] = RoofData.data["path_data"]
|
||||
target_element = tool.Ifc.get_entity(target_obj)
|
||||
target_props = target_obj.BIMRoofProperties
|
||||
|
||||
target_props.set_props_kwargs_from_ifc_data(data)
|
||||
update_bbim_roof_pset(target_element, data)
|
||||
refresh()
|
||||
update_roof_modifier_bmesh(target_obj)
|
||||
update_roof_modifier_ifc_data(context)
|
||||
|
||||
context.view_layer.objects.active = source_obj
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class FinishEditingRoofPath(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.finish_editing_roof_path"
|
||||
bl_label = "Finish Editing Roof Path"
|
||||
|
||||
@@ -649,13 +649,12 @@ class BIM_PT_roof(bpy.types.Panel):
|
||||
self.layout.prop(props, prop)
|
||||
|
||||
update_roof_modifier_bmesh(obj)
|
||||
|
||||
elif props.is_editing_path:
|
||||
row.operator("bim.finish_editing_roof_path", icon="CHECKMARK", text="")
|
||||
row.operator("bim.cancel_editing_roof_path", icon="CANCEL", text="")
|
||||
|
||||
else:
|
||||
row.operator("bim.enable_editing_roof", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.copy_roof_parameters", icon="COPYDOWN", text="")
|
||||
row.operator("bim.enable_editing_roof_path", icon="ANIM", text="")
|
||||
row.operator("bim.remove_roof", icon="X", text="")
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import bpy
|
||||
import bmesh
|
||||
import json
|
||||
import os
|
||||
from ifcopenshell import entity_instance
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.core.tool
|
||||
@@ -922,58 +923,131 @@ class Blender(bonsai.core.tool.Blender):
|
||||
|
||||
class Modifier:
|
||||
@classmethod
|
||||
def is_eligible_for_railing_modifier(cls, obj):
|
||||
def try_applying_edit_mode(cls, obj: bpy.types.Object, element: entity_instance) -> bool:
|
||||
"""Tries to validate the current BIM modifier parameters for the active object
|
||||
Goes into path editing mode if the modifier supports it
|
||||
|
||||
Returns True if an action was taken, False otherwise
|
||||
"""
|
||||
if cls.is_roof(element):
|
||||
if cls.is_editing_roof_parameters(obj):
|
||||
bpy.ops.bim.finish_editing_roof()
|
||||
bpy.ops.bim.enable_editing_roof_path()
|
||||
elif cls.is_railing(element):
|
||||
if cls.is_editing_railing_parameters(obj):
|
||||
bpy.ops.bim.finish_editing_railing()
|
||||
bpy.ops.bim.enable_editing_railing_path()
|
||||
elif cls.is_editing_stair_parameters(obj):
|
||||
bpy.ops.bim.finish_editing_stair()
|
||||
elif cls.is_editing_door_parameters(obj):
|
||||
bpy.ops.bim.finish_editing_door()
|
||||
elif cls.is_editing_window_parameters(obj):
|
||||
bpy.ops.bim.finish_editing_window()
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def try_canceling_editing_modifier_parameters_or_path(cls, obj: bpy.types.Object) -> bool:
|
||||
"""Tries to cancel the current BIM modifier parameters or path edition for the active object
|
||||
|
||||
Returns True if an action was taken, False otherwise
|
||||
"""
|
||||
if cls.is_editing_railing_path(obj):
|
||||
bpy.ops.bim.cancel_editing_railing_path()
|
||||
elif cls.is_editing_roof_path(obj):
|
||||
bpy.ops.bim.cancel_editing_roof_path()
|
||||
elif cls.is_editing_railing_parameters(obj):
|
||||
bpy.ops.bim.cancel_editing_railing()
|
||||
elif cls.is_editing_door_parameters(obj):
|
||||
bpy.ops.bim.cancel_editing_door()
|
||||
elif cls.is_editing_window_parameters(obj):
|
||||
bpy.ops.bim.cancel_editing_window()
|
||||
elif cls.is_editing_roof_parameters(obj):
|
||||
bpy.ops.bim.cancel_editing_roof()
|
||||
elif cls.is_editing_stair_parameters(obj):
|
||||
bpy.ops.bim.cancel_editing_stair()
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_railing_modifier(cls, obj: bpy.types.Object)-> bool:
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcRailing", "IfcRailingType"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_stair_modifier(cls, obj):
|
||||
def is_eligible_for_stair_modifier(cls, obj: bpy.types.Object)-> bool:
|
||||
return tool.Blender.is_object_an_ifc_class(
|
||||
obj, ("IfcStairFlight", "IfcStairFlightType", "IfcMember", "IfcMemberType", "IfcStair", "IfcStairType")
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_window_modifier(cls, obj):
|
||||
def is_eligible_for_window_modifier(cls, obj: bpy.types.Object)-> bool:
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcWindow", "IfcWindowType", "IfcWindowStyle"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_door_modifier(cls, obj):
|
||||
def is_eligible_for_door_modifier(cls, obj: bpy.types.Object)-> bool:
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcDoor", "IfcDoorType", "IfcDoorStyle"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_roof_modifier(cls, obj):
|
||||
def is_eligible_for_roof_modifier(cls, obj: bpy.types.Object)-> bool:
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcRoof", "IfcRoofType"))
|
||||
|
||||
@classmethod
|
||||
def is_railing(cls, element):
|
||||
def is_railing(cls, element: entity_instance)-> bool:
|
||||
return tool.Pset.get_element_pset(element, "BBIM_Railing")
|
||||
|
||||
@classmethod
|
||||
def is_roof(cls, element):
|
||||
def is_roof(cls, element: entity_instance)-> bool:
|
||||
return tool.Pset.get_element_pset(element, "BBIM_Roof")
|
||||
|
||||
@classmethod
|
||||
def is_window(cls, element):
|
||||
def is_window(cls, element: entity_instance)-> bool:
|
||||
return tool.Pset.get_element_pset(element, "BBIM_Window")
|
||||
|
||||
@classmethod
|
||||
def is_door(cls, element):
|
||||
def is_door(cls, element: entity_instance)-> bool:
|
||||
return tool.Pset.get_element_pset(element, "BBIM_Door")
|
||||
|
||||
@classmethod
|
||||
def is_stair(cls, element):
|
||||
def is_stair(cls, element: entity_instance)-> bool:
|
||||
return tool.Pset.get_element_pset(element, "BBIM_Stair")
|
||||
|
||||
@classmethod
|
||||
def is_editing_parameters(cls, obj):
|
||||
return obj.BIMRailingProperties.is_editing or obj.BIMRoofProperties.is_editing
|
||||
def is_editing_railing_path(cls, obj: bpy.types.Object):
|
||||
return obj.BIMRailingProperties.is_editing_path
|
||||
|
||||
@classmethod
|
||||
def is_modifier_with_non_editable_path(cls, element):
|
||||
def is_editing_roof_path(cls, obj: bpy.types.Object)-> bool:
|
||||
return obj.BIMRoofProperties.is_editing_path
|
||||
|
||||
@classmethod
|
||||
def is_editing_railing_parameters(cls, obj: bpy.types.Object)-> bool:
|
||||
return obj.BIMRailingProperties.is_editing
|
||||
|
||||
@classmethod
|
||||
def is_editing_roof_parameters(cls, obj: bpy.types.Object)-> bool:
|
||||
return obj.BIMRoofProperties.is_editing
|
||||
|
||||
@classmethod
|
||||
def is_editing_window_parameters(cls, obj: bpy.types.Object)-> bool:
|
||||
return obj.BIMWindowProperties.is_editing
|
||||
|
||||
@classmethod
|
||||
def is_editing_door_parameters(cls, obj: bpy.types.Object)-> bool:
|
||||
return obj.BIMDoorProperties.is_editing
|
||||
|
||||
@classmethod
|
||||
def is_editing_stair_parameters(cls, obj: bpy.types.Object)-> bool:
|
||||
return obj.BIMStairProperties.is_editing
|
||||
|
||||
@classmethod
|
||||
def is_modifier_with_non_editable_path(cls, element: entity_instance)-> bool:
|
||||
return cls.is_stair(element) or cls.is_door(element) or cls.is_window(element)
|
||||
|
||||
class Array:
|
||||
@classmethod
|
||||
def bake_children_transform(cls, parent_element, item):
|
||||
def bake_children_transform(cls, parent_element: entity_instance, item):
|
||||
modifier_data = list(cls.get_modifiers_data(parent_element))[item]
|
||||
children = cls.get_children_objects(modifier_data)
|
||||
for child in children:
|
||||
|
||||
Reference in New Issue
Block a user