You can now directly apply an ifc array modifier

Previously one would have to click on "remove" then "keep objects"
This commit is contained in:
Gorgious
2023-07-23 15:13:04 +02:00
parent c56d9b01de
commit 8b644d8415
5 changed files with 50 additions and 22 deletions
@@ -45,6 +45,7 @@ classes = (
array.DisableEditingArray,
array.EditArray,
array.EnableEditingArray,
array.ApplyArray,
array.RemoveArray,
array.SelectArrayParent,
array.SelectAllArrayObjects,
@@ -135,11 +135,26 @@ class EditArray(bpy.types.Operator, tool.Ifc.Operator):
data = json.dumps(data)
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": data})
tool.Blender.Modifier.Array.lock_children_transform(element, True)
tool.Blender.Modifier.Array.set_children_lock_state(element, self.item, True)
tool.Blender.Modifier.Array.constrain_children_to_parent(element)
return {"FINISHED"}
class ApplyArray(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.apply_array"
bl_label = "Apply Array"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Apply the array and keep children as separate entities. Only available for the last array"
def _execute(self, context):
obj = context.active_object
element = tool.Ifc.get_entity(obj)
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Array")
data = json.loads(pset["Data"])
bpy.ops.bim.remove_array(item=len(data) - 1, keep_objs=True)
return {"FINISHED"}
class RemoveArray(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_array"
bl_label = "Remove Array"
@@ -169,11 +184,11 @@ class RemoveArray(bpy.types.Operator, tool.Ifc.Operator):
except:
return {"FINISHED"}
tool.Model.regenerate_array(parent, data, self.keep_objs)
if self.keep_objs:
tool.Blender.Modifier.Array.unconstrain_children_from_parent(element)
tool.Blender.Modifier.Array.lock_children_transform(element, False)
tool.Blender.Modifier.Array.bake_children_transform(element, self.item)
tool.Blender.Modifier.Array.set_children_lock_state(element, self.item, False)
tool.Model.regenerate_array(parent, data, self.keep_objs)
pset = tool.Ifc.get().by_id(pset["id"])
if len(data) == 1:
@@ -182,16 +197,10 @@ class RemoveArray(bpy.types.Operator, tool.Ifc.Operator):
del data[self.item]
data = json.dumps(data)
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": data})
tool.Blender.Modifier.Array.constrain_children_to_parent(element)
return {"FINISHED"}
def draw(self, context):
row = self.layout.row()
row.prop(self, "keep_objs")
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
class SelectArrayParent(bpy.types.Operator):
bl_idname = "bim.select_array_parent"
@@ -224,6 +224,9 @@ class BIM_PT_array(bpy.types.Panel):
name = f"{array['count']} Items ({array.get('method', 'OFFSET').capitalize()})"
row.label(text=name, icon="MOD_ARRAY")
row.operator("bim.enable_editing_array", icon="GREASEPENCIL", text="").item = i
apply_button = row.row(align=True)
apply_button.operator("bim.apply_array", text="", icon="CHECKMARK")
apply_button.enabled = i == len(ArrayData.data["parameters"]["data_dict"]) - 1
row.operator("bim.remove_array", icon="X", text="").item = i
row = box.row(align=True)
icon = "EMPTY_ARROWS" if array.get("use_local_space", False) else "EMPTY_AXIS"
+23 -10
View File
@@ -523,31 +523,44 @@ class Blender:
class Array:
@classmethod
def constrain_children_to_parent(cls, parent_element):
parent_obj = tool.Ifc.get_object(parent_element)
children = cls.get_all_children_objects(parent_element)
def bake_children_transform(cls, parent_element, item):
modifier_data = list(cls.get_modifiers_data(parent_element))[item]
children = cls.get_children_objects(modifier_data)
for child in children:
constraint = next(
(c for c in child.constraints if c.type == "CHILD_OF"), None
) or child.constraints.new("CHILD_OF")
constraint.target = parent_obj
constraint = next((c for c in child.constraints if c.type == "CHILD_OF"), None)
if constraint:
with bpy.context.temp_override(object=child):
bpy.ops.constraint.apply(constraint=constraint.name, owner="OBJECT")
@classmethod
def unconstrain_children_from_parent(cls, parent_element):
def constrain_children_to_parent(cls, parent_element):
parent_obj = tool.Ifc.get_object(parent_element)
children = cls.get_all_children_objects(parent_element)
for child in children:
constraint = next((c for c in child.constraints if c.type == "CHILD_OF"), None)
if constraint:
child.constraints.remove(constraint)
constraint = child.constraints.new("CHILD_OF")
constraint.target = parent_obj
@classmethod
def lock_children_transform(cls, parent_element, lock_state=True):
for child_obj in cls.get_all_children_objects(parent_element):
def set_children_lock_state(cls, parent_element, item, lock_state=True):
modifier_data = list(cls.get_modifiers_data(parent_element))[item]
children = cls.get_children_objects(modifier_data)
for child_obj in children:
for prop in ("lock_location", "lock_rotation", "lock_scale"):
attr = getattr(child_obj, prop)
for axis_idx in range(3):
attr[axis_idx] = lock_state
@classmethod
def remove_constraints(cls, parent_element):
children = cls.get_all_children_objects(parent_element)
for child in children:
constraint = next((c for c in child.constraints if c.type == "CHILD_OF"), None)
if constraint:
child.constraints.remove(constraint)
@classmethod
def get_all_objects(cls, parent_element):
parent_obj = tool.Ifc.get_object(parent_element)
+2
View File
@@ -529,6 +529,8 @@ class Model(blenderbim.core.tool.Model):
@classmethod
def regenerate_array(cls, parent, data, keep_objs=False):
tool.Blender.Modifier.Array.remove_constraints(tool.Ifc.get_entity(parent))
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
obj_stack = [parent]