diff --git a/src/blenderbim/blenderbim/bim/module/model/array.py b/src/blenderbim/blenderbim/bim/module/model/array.py index 1f647ca176..dfbf43e94f 100644 --- a/src/blenderbim/blenderbim/bim/module/model/array.py +++ b/src/blenderbim/blenderbim/bim/module/model/array.py @@ -34,7 +34,7 @@ class AddArray(bpy.types.Operator, tool.Ifc.Operator): obj = context.active_object element = tool.Ifc.get_entity(obj) - array = {"children": [], "count": 1, "x": 0.0, "y": 0.0, "z": 0.0} + array = {"children": [], "count": 1, "x": 0.0, "y": 0.0, "z": 0.0, "use_local_space": True} pset = ifcopenshell.util.element.get_pset(element, "BBIM_Array") @@ -61,7 +61,27 @@ class DisableEditingArray(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER"} def _execute(self, context): - props = context.active_object.BIMArrayProperties.is_editing = -1 + context.active_object.BIMArrayProperties.is_editing = -1 + return {"FINISHED"} + + +class EnableEditingArray(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.enable_editing_array" + bl_label = "Enable Editing Array" + bl_options = {"REGISTER"} + item: bpy.props.IntProperty() + + def _execute(self, context): + obj = context.active_object + element = tool.Ifc.get_entity(obj) + data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Array", "Data"))[self.item] + props = obj.BIMArrayProperties + props.count = data["count"] + props.x = data["x"] + props.y = data["y"] + props.z = data["z"] + props.use_local_space = data.get("use_local_space", False) + props.is_editing = self.item return {"FINISHED"} @@ -84,6 +104,7 @@ class EditArray(bpy.types.Operator, tool.Ifc.Operator): "x": props.x, "y": props.y, "z": props.z, + "use_local_space": props.use_local_space, } props.is_editing = -1 @@ -101,25 +122,6 @@ class EditArray(bpy.types.Operator, tool.Ifc.Operator): return {"FINISHED"} -class EnableEditingArray(bpy.types.Operator, tool.Ifc.Operator): - bl_idname = "bim.enable_editing_array" - bl_label = "Enable Editing Array" - bl_options = {"REGISTER"} - item: bpy.props.IntProperty() - - def _execute(self, context): - obj = context.active_object - element = tool.Ifc.get_entity(obj) - data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Array", "Data"))[self.item] - props = obj.BIMArrayProperties - props.count = data["count"] - props.x = data["x"] - props.y = data["y"] - props.z = data["z"] - props.is_editing = self.item - return {"FINISHED"} - - class RemoveArray(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.remove_array" bl_label = "Remove Array" diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py index 4fc12357df..8561c4b122 100644 --- a/src/blenderbim/blenderbim/bim/module/model/prop.py +++ b/src/blenderbim/blenderbim/bim/module/model/prop.py @@ -249,11 +249,18 @@ class BIMModelProperties(PropertyGroup): class BIMArrayProperties(PropertyGroup): - is_editing: bpy.props.IntProperty(default=-1) + is_editing: bpy.props.IntProperty( + default=-1, description="Currently edited array index. -1 if not in array editing mode." + ) count: bpy.props.IntProperty(name="Count", default=0) x: bpy.props.FloatProperty(name="X", default=0) y: bpy.props.FloatProperty(name="Y", default=0) z: bpy.props.FloatProperty(name="Z", default=0) + use_local_space: bpy.props.BoolProperty( + name="Use Local Space", + description="Use local space for array items offset instead of world space", + default=True, + ) class BIMStairProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/model/ui.py b/src/blenderbim/blenderbim/bim/module/model/ui.py index 0326713ef6..3b81a011ab 100644 --- a/src/blenderbim/blenderbim/bim/module/model/ui.py +++ b/src/blenderbim/blenderbim/bim/module/model/ui.py @@ -224,6 +224,8 @@ class BIM_PT_array(bpy.types.Panel): row.operator("bim.edit_array", icon="CHECKMARK", text="").item = i row.operator("bim.disable_editing_array", icon="CANCEL", text="") row = box.row(align=True) + row.prop(props, "use_local_space") + row = box.row(align=True) row.prop(props, "x") row.prop(props, "y") row.prop(props, "z") @@ -234,6 +236,8 @@ class BIM_PT_array(bpy.types.Panel): row.operator("bim.enable_editing_array", icon="GREASEPENCIL", text="").item = i row.operator("bim.remove_array", icon="X", text="").item = i row = box.row(align=True) + row.label(text=f"Use Local Space: {array.get('use_local_space', False)}") + row = box.row(align=True) row.label(text=f"X: {array['x']}") row.label(text=f"Y: {array['y']}") row.label(text=f"Z: {array['z']}") diff --git a/src/blenderbim/blenderbim/tool/model.py b/src/blenderbim/blenderbim/tool/model.py index 96b8229ae4..d1c1f13728 100644 --- a/src/blenderbim/blenderbim/tool/model.py +++ b/src/blenderbim/blenderbim/tool/model.py @@ -153,10 +153,12 @@ class Model(blenderbim.core.tool.Model): cls.circles = [] if isinstance(axis, list): - cls.vertices.extend([ - position @ Vector(cls.convert_unit_to_si(axis[0])).to_3d(), - position @ Vector(cls.convert_unit_to_si(axis[1])).to_3d(), - ]) + cls.vertices.extend( + [ + position @ Vector(cls.convert_unit_to_si(axis[0])).to_3d(), + position @ Vector(cls.convert_unit_to_si(axis[1])).to_3d(), + ] + ) cls.edges.append([0, 1]) else: cls.import_curve(obj, position, axis) @@ -405,6 +407,7 @@ class Model(blenderbim.core.tool.Model): def regenerate_array(cls, parent, data): unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) obj_stack = [parent] + for array in data: child_i = 0 existing_children = set(array["children"]) @@ -412,7 +415,7 @@ class Model(blenderbim.core.tool.Model): children_elements = [] children_objs = [] base_offset = Vector([array["x"], array["y"], array["z"]]) * unit_scale - for i in range(0, array["count"]): + for i in range(array["count"]): if i == 0: continue offset = base_offset * i @@ -441,7 +444,8 @@ class Model(blenderbim.core.tool.Model): ) new_matrix = obj.matrix_world.copy() - new_matrix.col[3] = (obj.matrix_world.col[3].to_3d() + offset).to_4d() + current_obj_offset = obj.matrix_world @ offset if array["use_local_space"] else offset + new_matrix.col[3] = (obj.matrix_world.col[3].to_3d() + current_obj_offset).to_4d() child_obj.matrix_world = new_matrix children_objs.append(child_obj) children_elements.append(child_element)