Merge pull request #5930 from Gorgious56/improve_modifiers

Modifiers QOL
This commit is contained in:
Gorgious56
2025-01-06 12:10:26 +01:00
committed by GitHub
7 changed files with 136 additions and 29 deletions
@@ -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 = {}
+36 -1
View File
@@ -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"
+1 -2
View File
@@ -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="")
+88 -14
View File
@@ -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: