mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Clicking on the "Select all array objects" button now sets the parent object as active #3492
Moved the array objects fetching code to tool.Blender Also a bit of housekeeping and fixing minor typos here and there
This commit is contained in:
@@ -422,7 +422,7 @@ class IfcImporter:
|
||||
for representation in representations:
|
||||
items = representation["raw"].Items or [] # Be forgiving of invalid IFCs because Revit :(
|
||||
if len(items) == 1 and items[0].is_a("IfcSweptDiskSolid"):
|
||||
if tool.Pset.get_element_pset(element, "BBIM_Railing"):
|
||||
if tool.Blender.Modifier.is_railing(element):
|
||||
return False
|
||||
return True
|
||||
elif len(items) and ( # See #2508 why we accommodate for invalid IFCs here
|
||||
@@ -430,7 +430,7 @@ class IfcImporter:
|
||||
and len({i.is_a() for i in items}) == 1
|
||||
and len({i.Radius for i in items}) == 1
|
||||
):
|
||||
if tool.Pset.get_element_pset(element, "BBIM_Railing"):
|
||||
if tool.Blender.Modifier.is_railing(element):
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -1433,9 +1433,9 @@ class OverrideModeSetObject(bpy.types.Operator):
|
||||
profile = tool.Ifc.get().by_id(profile_id)
|
||||
if tool.Ifc.get_object(profile): # We are editing an arbitrary profile
|
||||
bpy.ops.bim.edit_arbitrary_profile()
|
||||
elif tool.Pset.get_element_pset(element, "BBIM_Railing"):
|
||||
elif tool.Blender.Modifier.is_railing(element):
|
||||
bpy.ops.bim.finish_editing_railing_path()
|
||||
elif tool.Pset.get_element_pset(element, "BBIM_Roof"):
|
||||
elif tool.Blender.Modifier.is_roof(element):
|
||||
bpy.ops.bim.finish_editing_roof_path()
|
||||
elif tool.Model.get_usage_type(element) == "PROFILE":
|
||||
bpy.ops.bim.edit_extrusion_axis()
|
||||
|
||||
@@ -217,10 +217,10 @@ class RemoveConstituent(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
constituent = tool.Ifc.get().by_id(self.constituent)
|
||||
for material_set in layer.ToMaterialConstituentSet:
|
||||
for material_set in constituent.ToMaterialConstituentSet:
|
||||
if len(material_set.MaterialConstituents) == 1:
|
||||
self.report({"ERROR"}, "At least one constituent must exist")
|
||||
return {"ERROR"}
|
||||
return {"CANCELLED"}
|
||||
ifcopenshell.api.run("material.remove_constituent", tool.Ifc.get(), constituent=constituent)
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ class RemoveProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
for material_set in profile.ToMaterialProfileSet:
|
||||
if len(material_set.MaterialProfiles) == 1:
|
||||
self.report({"ERROR"}, "At least one profile must exist")
|
||||
return {"ERROR"}
|
||||
return {"CANCELLED"}
|
||||
ifcopenshell.api.run("material.remove_profile", tool.Ifc.get(), profile=profile)
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ class RemoveLayer(bpy.types.Operator, tool.Ifc.Operator):
|
||||
for material_set in layer.ToMaterialLayerSet:
|
||||
if len(material_set.MaterialLayers) == 1:
|
||||
self.report({"ERROR"}, "At least one layer must exist")
|
||||
return {"ERROR"}
|
||||
return {"CANCELLED"}
|
||||
ifcopenshell.api.run("material.remove_layer", tool.Ifc.get(), layer=layer)
|
||||
|
||||
|
||||
|
||||
@@ -152,9 +152,11 @@ class RemoveArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Array")
|
||||
data = json.loads(pset["Data"])
|
||||
data[self.item]["count"] = 1
|
||||
|
||||
|
||||
if (self.keep_objs) & (self.item < (len(data) - 1)):
|
||||
self.report({"INFO"}, "Keeping the objects is only allowed when you are removing the last Array of the object")
|
||||
self.report(
|
||||
{"INFO"}, "Keeping the objects is only allowed when you are removing the last Array of the object"
|
||||
)
|
||||
return {"FINISHED"}
|
||||
|
||||
props.is_editing = -1
|
||||
@@ -188,46 +190,38 @@ class SelectArrayParent(bpy.types.Operator):
|
||||
bl_idname = "bim.select_array_parent"
|
||||
bl_label = "Select Array Parent"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
parent: bpy.props.StringProperty()
|
||||
parent: bpy.props.StringProperty(description="Parent Element GUID")
|
||||
|
||||
def execute(self, context):
|
||||
try:
|
||||
element = tool.Ifc.get().by_guid(self.parent)
|
||||
except:
|
||||
return {"FINISHED"}
|
||||
self.report({"ERROR"}, f"Couldn't find array parent by guid '{self.parent}'")
|
||||
return {"CANCELLED"}
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if obj:
|
||||
context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
tool.Blender.select_and_activate_single_object(context, active_object=obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
class SelectAllArrayObjects(bpy.types.Operator):
|
||||
bl_idname = "bim.select_all_array_objects"
|
||||
bl_label = "Select All Array Objects"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
parent: bpy.props.StringProperty()
|
||||
parent: bpy.props.StringProperty(description="Parent Element GUID")
|
||||
|
||||
def execute(self, context):
|
||||
try:
|
||||
element = tool.Ifc.get().by_guid(self.parent)
|
||||
except:
|
||||
return {"FINISHED"}
|
||||
|
||||
obj = tool.Ifc.get_object(element)
|
||||
obj.select_set(True)
|
||||
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Array")
|
||||
data = json.loads(pset["Data"])
|
||||
for i in range(len(data)):
|
||||
for child in data[i]["children"]:
|
||||
element = tool.Ifc.get().by_guid(child)
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if obj:
|
||||
context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
parent_element = tool.Ifc.get().by_guid(self.parent)
|
||||
except RuntimeError:
|
||||
self.report({"ERROR"}, f"Couldn't find array parent by guid '{self.parent}'")
|
||||
return {"CANCELLED"}
|
||||
|
||||
array_objects = tool.Blender.Modifier.Array.get_all_objects(parent_element)
|
||||
tool.Blender.set_objects_selection(context, active_object=array_objects[0], selected_objects=array_objects)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class Input3DCursorXArray(bpy.types.Operator):
|
||||
bl_idname = "bim.input_cursor_x_array"
|
||||
bl_label = "Get 3d Cursor X Input for Array"
|
||||
|
||||
@@ -150,7 +150,7 @@ class ReloadSelectedIfcFile(bpy.types.Operator):
|
||||
valid_file = os.path.exists(filepath) and "ifc" in os.path.splitext(filepath)[1].lower()
|
||||
if not valid_file:
|
||||
self.report({"ERROR"}, f"Couldn't find .ifc file by the path '{filepath}'")
|
||||
return {"ERROR"}
|
||||
return {"CANCELLED"}
|
||||
context.scene.BIMProperties.ifc_file = context.scene.BIMProperties.ifc_file
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import json
|
||||
import ifcopenshell.api
|
||||
import blenderbim.tool as tool
|
||||
from mathutils import Vector
|
||||
@@ -457,33 +458,40 @@ class Blender:
|
||||
else:
|
||||
return {"CANCELLED"}
|
||||
|
||||
@classmethod
|
||||
def is_object_an_ifc_class(cls, obj, classes):
|
||||
if not tool.Ifc.get():
|
||||
return False
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
return element and element.is_a() in classes
|
||||
|
||||
@classmethod
|
||||
def get_object_from_guid(cls, guid):
|
||||
element = tool.Ifc.get().by_guid(guid)
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if obj:
|
||||
return obj
|
||||
|
||||
class Modifier:
|
||||
@classmethod
|
||||
def is_object_an_ifc_class(cls, obj, classes):
|
||||
if not tool.Ifc.get():
|
||||
return False
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
return element and element.is_a() in classes
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_railing_modifier(cls, obj):
|
||||
return cls.is_object_an_ifc_class(obj, ("IfcRailing", "IfcRailingType"))
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcRailing", "IfcRailingType"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_stair_modifier(cls, obj):
|
||||
return cls.is_object_an_ifc_class(obj, ("IfcStairFlight", "IfcStairFlightType"))
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcStairFlight", "IfcStairFlightType"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_window_modifier(cls, obj):
|
||||
return cls.is_object_an_ifc_class(obj, ("IfcWindow", "IfcWindowType", "IfcWindowStyle"))
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcWindow", "IfcWindowType", "IfcWindowStyle"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_door_modifier(cls, obj):
|
||||
return cls.is_object_an_ifc_class(obj, ("IfcDoor", "IfcDoorType", "IfcDoorStyle"))
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcDoor", "IfcDoorType", "IfcDoorStyle"))
|
||||
|
||||
@classmethod
|
||||
def is_eligible_for_roof_modifier(cls, obj):
|
||||
return cls.is_object_an_ifc_class(obj, ("IfcRoof", "IfcRoofType"))
|
||||
return tool.Blender.is_object_an_ifc_class(obj, ("IfcRoof", "IfcRoofType"))
|
||||
|
||||
@classmethod
|
||||
def is_railing(cls, element):
|
||||
@@ -512,3 +520,29 @@ class Blender:
|
||||
@classmethod
|
||||
def is_modifier_with_non_editable_path(cls, element):
|
||||
return cls.is_stair(element) or cls.is_door(element) or cls.is_window(element)
|
||||
|
||||
class Array:
|
||||
@classmethod
|
||||
def get_all_objects(cls, parent_element):
|
||||
parent_obj = tool.Ifc.get_object(parent_element)
|
||||
children_objects = list(cls.get_all_children_objects(parent_element))
|
||||
array_objects = [parent_obj] + children_objects # We ensure the parent is at index 0
|
||||
return array_objects
|
||||
|
||||
@classmethod
|
||||
def get_all_children_objects(cls, parent_element):
|
||||
for array_modifier in cls.get_modifiers_data(parent_element):
|
||||
yield from cls.get_children_objects(array_modifier)
|
||||
|
||||
@classmethod
|
||||
def get_modifiers_data(cls, parent_element):
|
||||
array_pset = ifcopenshell.util.element.get_pset(parent_element, "BBIM_Array")
|
||||
for modifier_data in json.loads(array_pset["Data"]):
|
||||
yield modifier_data
|
||||
|
||||
@classmethod
|
||||
def get_children_objects(cls, modifier_data):
|
||||
for child_guid in modifier_data["children"]:
|
||||
child_obj = tool.Blender.get_object_from_guid(child_guid)
|
||||
if child_obj:
|
||||
yield child_obj
|
||||
|
||||
Reference in New Issue
Block a user