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:
Gorgious
2023-07-23 13:03:06 +02:00
parent f5d5f44458
commit c1c6dfc47e
6 changed files with 73 additions and 45 deletions
+2 -2
View File
@@ -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"
+1 -1
View File
@@ -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"}
+46 -12
View File
@@ -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