mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 22:31:55 +00:00
You can now array IFC elements parametrically
This commit is contained in:
@@ -17,9 +17,15 @@
|
|||||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from . import handler, prop, ui, grid, product, wall, slab, stair, opening, pie, workspace, profile
|
from . import handler, prop, ui, grid, array, product, wall, slab, stair, opening, pie, workspace, profile
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
|
array.AddArray,
|
||||||
|
array.DisableEditingArray,
|
||||||
|
array.EditArray,
|
||||||
|
array.EnableEditingArray,
|
||||||
|
array.RemoveArray,
|
||||||
|
array.SelectArrayParent,
|
||||||
product.AddConstrTypeInstance,
|
product.AddConstrTypeInstance,
|
||||||
product.AddEmptyType,
|
product.AddEmptyType,
|
||||||
product.AlignProduct,
|
product.AlignProduct,
|
||||||
@@ -66,7 +72,9 @@ classes = (
|
|||||||
prop.ConstrClassInfo,
|
prop.ConstrClassInfo,
|
||||||
prop.ConstrBrowserState,
|
prop.ConstrBrowserState,
|
||||||
prop.BIMModelProperties,
|
prop.BIMModelProperties,
|
||||||
|
prop.BIMArrayProperties,
|
||||||
ui.BIM_PT_authoring,
|
ui.BIM_PT_authoring,
|
||||||
|
ui.BIM_PT_array,
|
||||||
ui.DisplayConstrTypesUI,
|
ui.DisplayConstrTypesUI,
|
||||||
ui.LaunchTypeManager,
|
ui.LaunchTypeManager,
|
||||||
ui.HelpConstrTypes,
|
ui.HelpConstrTypes,
|
||||||
@@ -87,6 +95,7 @@ def register():
|
|||||||
if not bpy.app.background:
|
if not bpy.app.background:
|
||||||
bpy.utils.register_tool(workspace.BimTool, after={"builtin.scale_cage"}, separator=True, group=True)
|
bpy.utils.register_tool(workspace.BimTool, after={"builtin.scale_cage"}, separator=True, group=True)
|
||||||
bpy.types.Scene.BIMModelProperties = bpy.props.PointerProperty(type=prop.BIMModelProperties)
|
bpy.types.Scene.BIMModelProperties = bpy.props.PointerProperty(type=prop.BIMModelProperties)
|
||||||
|
bpy.types.Object.BIMArrayProperties = bpy.props.PointerProperty(type=prop.BIMArrayProperties)
|
||||||
bpy.types.VIEW3D_MT_mesh_add.append(grid.add_object_button)
|
bpy.types.VIEW3D_MT_mesh_add.append(grid.add_object_button)
|
||||||
bpy.types.VIEW3D_MT_mesh_add.append(stair.add_object_button)
|
bpy.types.VIEW3D_MT_mesh_add.append(stair.add_object_button)
|
||||||
bpy.types.VIEW3D_MT_add.append(ui.add_menu)
|
bpy.types.VIEW3D_MT_add.append(ui.add_menu)
|
||||||
@@ -103,6 +112,7 @@ def unregister():
|
|||||||
if not bpy.app.background:
|
if not bpy.app.background:
|
||||||
bpy.utils.unregister_tool(workspace.BimTool)
|
bpy.utils.unregister_tool(workspace.BimTool)
|
||||||
del bpy.types.Scene.BIMModelProperties
|
del bpy.types.Scene.BIMModelProperties
|
||||||
|
del bpy.types.Object.BIMArrayProperties
|
||||||
bpy.app.handlers.load_post.remove(handler.load_post)
|
bpy.app.handlers.load_post.remove(handler.load_post)
|
||||||
bpy.types.VIEW3D_MT_mesh_add.remove(grid.add_object_button)
|
bpy.types.VIEW3D_MT_mesh_add.remove(grid.add_object_button)
|
||||||
bpy.types.VIEW3D_MT_mesh_add.remove(stair.add_object_button)
|
bpy.types.VIEW3D_MT_mesh_add.remove(stair.add_object_button)
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
|
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of BlenderBIM Add-on.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import json
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api
|
||||||
|
import ifcopenshell.util.element
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
from mathutils import Vector
|
||||||
|
|
||||||
|
|
||||||
|
class AddArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.add_array"
|
||||||
|
bl_label = "Add Array"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
obj = context.active_object
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
|
||||||
|
array = {"children": [], "count": 1, "x": 0.0, "y": 0.0, "z": 0.0}
|
||||||
|
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
pset = psets.get("BBIM_Array", None)
|
||||||
|
|
||||||
|
if pset:
|
||||||
|
data = json.loads(pset["Data"])
|
||||||
|
data.append(array)
|
||||||
|
pset = tool.Ifc.get().by_id(pset["id"])
|
||||||
|
else:
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="BBIM_Array")
|
||||||
|
data = [array]
|
||||||
|
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"pset.edit_pset",
|
||||||
|
tool.Ifc.get(),
|
||||||
|
pset=pset,
|
||||||
|
properties={"Parent": element.GlobalId, "Data": json.dumps(data)},
|
||||||
|
)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class DisableEditingArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.disable_editing_array"
|
||||||
|
bl_label = "Disable Editing Array"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
props = context.active_object.BIMArrayProperties.is_editing = -1
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class EditArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.edit_array"
|
||||||
|
bl_label = "Edit Array"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
item: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
obj = context.active_object
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
props = obj.BIMArrayProperties
|
||||||
|
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
pset = psets["BBIM_Array"]
|
||||||
|
data = json.loads(pset["Data"])
|
||||||
|
data[self.item] = {
|
||||||
|
"children": data[self.item]["children"],
|
||||||
|
"count": props.count,
|
||||||
|
"x": props.x,
|
||||||
|
"y": props.y,
|
||||||
|
"z": props.z,
|
||||||
|
}
|
||||||
|
|
||||||
|
props.is_editing = -1
|
||||||
|
|
||||||
|
try:
|
||||||
|
parent = tool.Ifc.get_object(tool.Ifc.get().by_guid(pset["Parent"]))
|
||||||
|
except:
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
tool.Model.regenerate_array(parent, data)
|
||||||
|
|
||||||
|
pset = tool.Ifc.get().by_id(pset["id"])
|
||||||
|
data = json.dumps(data)
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": data})
|
||||||
|
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)
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
data = json.loads(psets["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
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.remove_array"
|
||||||
|
bl_label = "Remove Array"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
item: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
obj = context.active_object
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
props = obj.BIMArrayProperties
|
||||||
|
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
pset = psets["BBIM_Array"]
|
||||||
|
data = json.loads(pset["Data"])
|
||||||
|
data[self.item]["count"] = 1
|
||||||
|
|
||||||
|
props.is_editing = -1
|
||||||
|
|
||||||
|
try:
|
||||||
|
parent = tool.Ifc.get_object(tool.Ifc.get().by_guid(pset["Parent"]))
|
||||||
|
except:
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
tool.Model.regenerate_array(parent, data)
|
||||||
|
|
||||||
|
pset = tool.Ifc.get().by_id(pset["id"])
|
||||||
|
if len(data) == 1:
|
||||||
|
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||||
|
else:
|
||||||
|
del data[self.item]
|
||||||
|
data = json.dumps(data)
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": data})
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectArrayParent(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.select_array_parent"
|
||||||
|
bl_label = "Select Array Parent"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
parent: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
try:
|
||||||
|
element = tool.Ifc.get().by_guid(self.parent)
|
||||||
|
except:
|
||||||
|
return {"FINISHED"}
|
||||||
|
obj = tool.Ifc.get_object(element)
|
||||||
|
if obj:
|
||||||
|
context.view_layer.objects.active = obj
|
||||||
|
obj.select_set(True)
|
||||||
|
return {"FINISHED"}
|
||||||
@@ -18,8 +18,10 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
|
import json
|
||||||
import functools
|
import functools
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.element
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound
|
from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound
|
||||||
@@ -28,6 +30,7 @@ from blenderbim.bim.prop import get_ifc_entity_description, get_predefined_type_
|
|||||||
|
|
||||||
def refresh():
|
def refresh():
|
||||||
AuthoringData.is_loaded = False
|
AuthoringData.is_loaded = False
|
||||||
|
ArrayData.is_loaded = False
|
||||||
|
|
||||||
|
|
||||||
class AuthoringData:
|
class AuthoringData:
|
||||||
@@ -316,3 +319,29 @@ class AuthoringData:
|
|||||||
def relating_type_id_by_name(cls, ifc_class, relating_type):
|
def relating_type_id_by_name(cls, ifc_class, relating_type):
|
||||||
relating_types = [ct[0] for ct in cls.relating_types(ifc_class=ifc_class) if ct[1] == relating_type]
|
relating_types = [ct[0] for ct in cls.relating_types(ifc_class=ifc_class) if ct[1] == relating_type]
|
||||||
return None if len(relating_types) == 0 else relating_types[0]
|
return None if len(relating_types) == 0 else relating_types[0]
|
||||||
|
|
||||||
|
|
||||||
|
class ArrayData:
|
||||||
|
data = {}
|
||||||
|
is_loaded = False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load(cls):
|
||||||
|
cls.is_loaded = True
|
||||||
|
cls.data = { "parameters": cls.parameters() }
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parameters(cls):
|
||||||
|
element = tool.Ifc.get_entity(bpy.context.active_object)
|
||||||
|
if element:
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
parameters = psets.get("BBIM_Array", None)
|
||||||
|
if parameters:
|
||||||
|
try:
|
||||||
|
parent = tool.Ifc.get().by_guid(parameters["Parent"])
|
||||||
|
parameters["has_parent"] = True
|
||||||
|
parameters["parent_name"] = parent.Name or "Unnamed"
|
||||||
|
parameters["data"] = json.loads(parameters.get("Data", "[]") or "[]")
|
||||||
|
except:
|
||||||
|
parameters["has_parent"] = False
|
||||||
|
return parameters
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
# Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
|
||||||
#
|
#
|
||||||
# This file is part of BlenderBIM Add-on.
|
# This file is part of BlenderBIM Add-on.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -245,3 +245,11 @@ class BIMModelProperties(PropertyGroup):
|
|||||||
)
|
)
|
||||||
type_class: bpy.props.EnumProperty(items=get_type_class, name="IFC Class", update=update_type_class)
|
type_class: bpy.props.EnumProperty(items=get_type_class, name="IFC Class", update=update_type_class)
|
||||||
type_predefined_type: bpy.props.EnumProperty(items=get_type_predefined_type, name="Predefined Type", default=None)
|
type_predefined_type: bpy.props.EnumProperty(items=get_type_predefined_type, name="Predefined Type", default=None)
|
||||||
|
|
||||||
|
|
||||||
|
class BIMArrayProperties(PropertyGroup):
|
||||||
|
is_editing: bpy.props.IntProperty(default=-1)
|
||||||
|
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)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
# Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
|
||||||
#
|
#
|
||||||
# This file is part of BlenderBIM Add-on.
|
# This file is part of BlenderBIM Add-on.
|
||||||
#
|
#
|
||||||
@@ -17,8 +17,9 @@
|
|||||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import blenderbim.tool as tool
|
||||||
from bpy.types import Panel, Operator, Menu
|
from bpy.types import Panel, Operator, Menu
|
||||||
from blenderbim.bim.module.model.data import AuthoringData
|
from blenderbim.bim.module.model.data import AuthoringData, ArrayData
|
||||||
from blenderbim.bim.module.model.prop import store_cursor_position
|
from blenderbim.bim.module.model.prop import store_cursor_position
|
||||||
from blenderbim.bim.helper import prop_with_search
|
from blenderbim.bim.helper import prop_with_search
|
||||||
|
|
||||||
@@ -254,6 +255,57 @@ class HelpConstrTypes(Operator):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_array(bpy.types.Panel):
|
||||||
|
bl_label = "IFC Array"
|
||||||
|
bl_idname = "BIM_PT_array"
|
||||||
|
bl_space_type = "PROPERTIES"
|
||||||
|
bl_region_type = "WINDOW"
|
||||||
|
bl_context = "modifier"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return tool.Ifc.get() and tool.Ifc.get_entity(context.active_object)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
if not ArrayData.is_loaded:
|
||||||
|
ArrayData.load()
|
||||||
|
|
||||||
|
props = context.active_object.BIMArrayProperties
|
||||||
|
|
||||||
|
if ArrayData.data["parameters"]:
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.label(text=ArrayData.data["parameters"]["parent_name"], icon="CON_CHILDOF")
|
||||||
|
op = row.operator("bim.select_array_parent", icon="OBJECT_DATA", text="")
|
||||||
|
op.parent = ArrayData.data["parameters"]["Parent"]
|
||||||
|
if ArrayData.data["parameters"]["data"]:
|
||||||
|
row.operator("bim.add_array", icon="ADD", text="")
|
||||||
|
|
||||||
|
for i, array in enumerate(ArrayData.data["parameters"]["data"]):
|
||||||
|
box = self.layout.box()
|
||||||
|
if props.is_editing == i:
|
||||||
|
row = box.row(align=True)
|
||||||
|
row.prop(props, "count", icon="MOD_ARRAY")
|
||||||
|
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, "x")
|
||||||
|
row.prop(props, "y")
|
||||||
|
row.prop(props, "z")
|
||||||
|
else:
|
||||||
|
row = box.row(align=True)
|
||||||
|
row.label(text=f"{array['count']} Items", icon="MOD_ARRAY")
|
||||||
|
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"X: {array['x']}")
|
||||||
|
row.label(text=f"Y: {array['y']}")
|
||||||
|
row.label(text=f"Z: {array['z']}")
|
||||||
|
else:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text="No Array Found")
|
||||||
|
row.operator("bim.add_array", icon="ADD", text="")
|
||||||
|
|
||||||
|
|
||||||
class BIM_MT_model(Menu):
|
class BIM_MT_model(Menu):
|
||||||
bl_idname = "BIM_MT_model"
|
bl_idname = "BIM_MT_model"
|
||||||
bl_label = "IFC Objects"
|
bl_label = "IFC Objects"
|
||||||
|
|||||||
@@ -139,3 +139,61 @@ class Model(blenderbim.core.tool.Model):
|
|||||||
(obj.matrix_world @ Vector((max_x, 0.0, 0.0))).to_2d(),
|
(obj.matrix_world @ Vector((max_x, 0.0, 0.0))).to_2d(),
|
||||||
]
|
]
|
||||||
return axes
|
return axes
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
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"])
|
||||||
|
total_existing_children = len(array["children"])
|
||||||
|
children_elements = []
|
||||||
|
children_objs = []
|
||||||
|
for i in range(0, array["count"]):
|
||||||
|
if i == 0:
|
||||||
|
continue
|
||||||
|
offset = Vector((i * array["x"] * unit_scale, i * array["y"] * unit_scale, i * array["z"] * unit_scale))
|
||||||
|
for obj in obj_stack:
|
||||||
|
if child_i >= total_existing_children:
|
||||||
|
child_obj = tool.Spatial.duplicate_object_and_data(obj)
|
||||||
|
child_element = tool.Spatial.run_root_copy_class(obj=child_obj)
|
||||||
|
else:
|
||||||
|
global_id = array["children"][child_i]
|
||||||
|
try:
|
||||||
|
child_element = tool.Ifc.get().by_guid(global_id)
|
||||||
|
child_obj = tool.Ifc.get_object(child_element)
|
||||||
|
assert child_obj
|
||||||
|
except:
|
||||||
|
child_obj = tool.Spatial.duplicate_object_and_data(obj)
|
||||||
|
child_element = tool.Spatial.run_root_copy_class(obj=child_obj)
|
||||||
|
|
||||||
|
child_psets = ifcopenshell.util.element.get_psets(child_element)
|
||||||
|
child_pset = child_psets.get("BBIM_Array")
|
||||||
|
if child_pset:
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"pset.edit_pset",
|
||||||
|
tool.Ifc.get(),
|
||||||
|
product=child_element,
|
||||||
|
pset=tool.Ifc.get().by_id(child_pset["id"]),
|
||||||
|
properties={"Data": None},
|
||||||
|
)
|
||||||
|
|
||||||
|
new_matrix = obj.matrix_world.copy()
|
||||||
|
new_matrix.col[3] = (obj.matrix_world.col[3].to_3d() + offset).to_4d()
|
||||||
|
child_obj.matrix_world = new_matrix
|
||||||
|
children_objs.append(child_obj)
|
||||||
|
children_elements.append(child_element)
|
||||||
|
child_i += 1
|
||||||
|
obj_stack.extend(children_objs)
|
||||||
|
array["children"] = [e.GlobalId for e in children_elements]
|
||||||
|
|
||||||
|
removed_children = set(existing_children) - set(array["children"])
|
||||||
|
for removed_child in removed_children:
|
||||||
|
element = tool.Ifc.get().by_guid(removed_child)
|
||||||
|
obj = tool.Ifc.get_object(element)
|
||||||
|
if obj:
|
||||||
|
bpy.data.objects.remove(obj)
|
||||||
|
# TODO: Not sufficient, refactor OverrideDeleteTrait
|
||||||
|
|
||||||
|
bpy.context.view_layer.update()
|
||||||
|
|||||||
Reference in New Issue
Block a user