mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
New UI List in Sandbox panel to access, flip, remove, add, edit clipping planes
and some tweaks : - Disable possibility to edit clipping plane quad geometry - Add select and delete operators - Remove polls from CreateClippingPlane that prevented from using it in the Properties editor. The clipping plane is added near the origin when using the Add button in the panel
This commit is contained in:
@@ -97,8 +97,10 @@ for name in modules.keys():
|
||||
classes = [
|
||||
operator.AddIfcFile,
|
||||
operator.BIM_OT_add_section_plane,
|
||||
operator.BIM_OT_delete_object,
|
||||
operator.BIM_OT_open_webbrowser,
|
||||
operator.BIM_OT_remove_section_plane,
|
||||
operator.BIM_OT_select_object,
|
||||
operator.BIM_OT_show_description,
|
||||
operator.ClippingPlaneCutWithCappings,
|
||||
operator.EditBlenderCollection,
|
||||
@@ -131,6 +133,7 @@ classes = [
|
||||
prop.BIMMeshProperties,
|
||||
prop.BIMFacet,
|
||||
prop.BIMFilterGroup,
|
||||
ui.BIM_UL_clipping_plane,
|
||||
ui.BIM_UL_generic,
|
||||
ui.BIM_UL_topics,
|
||||
ui.BIM_ADDON_preferences,
|
||||
|
||||
@@ -1015,7 +1015,9 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator):
|
||||
return
|
||||
|
||||
linked_aggregate_group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), Name=self.group_name)
|
||||
ifcopenshell.api.run("group.assign_group", tool.Ifc.get(), products=[element], group=linked_aggregate_group)
|
||||
ifcopenshell.api.run(
|
||||
"group.assign_group", tool.Ifc.get(), products=[element], group=linked_aggregate_group
|
||||
)
|
||||
|
||||
def custom_incremental_naming_for_element_assembly(old_to_new):
|
||||
for new in old_to_new.values():
|
||||
@@ -1271,7 +1273,9 @@ class RefreshLinkedAggregate(bpy.types.Operator):
|
||||
|
||||
tool.Ifc.get_object(base_instance).select_set(True)
|
||||
|
||||
old_to_new = DuplicateMoveLinkedAggregate.execute_ifc_duplicate_linked_aggregate_operator(self, context)
|
||||
old_to_new = DuplicateMoveLinkedAggregate.execute_ifc_duplicate_linked_aggregate_operator(
|
||||
self, context
|
||||
)
|
||||
for old, new in old_to_new.items():
|
||||
new_obj = tool.Ifc.get_object(new[0])
|
||||
new_base_matrix = Matrix.LocRotScale(*duplicate_matrix)
|
||||
@@ -1443,7 +1447,9 @@ class OverrideModeSetEdit(bpy.types.Operator):
|
||||
for obj in selected_objs:
|
||||
if not obj:
|
||||
continue
|
||||
if not obj.data:
|
||||
obj_supports_edit_mode, message = tool.Blender.object_supports_edit_mode(obj)
|
||||
if not obj_supports_edit_mode:
|
||||
self.report({"INFO"}, message)
|
||||
obj.select_set(False)
|
||||
continue
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
@@ -1920,32 +1920,32 @@ class CreateClippingPlane(bpy.types.Operator):
|
||||
bl_label = "Create Clipping Plane"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.area.type == "VIEW_3D"
|
||||
|
||||
def execute(self, context):
|
||||
from bpy_extras.view3d_utils import region_2d_to_vector_3d, region_2d_to_origin_3d
|
||||
|
||||
# Clean up deleted planes
|
||||
|
||||
if len(bpy.context.scene.BIMProjectProperties.clipping_planes) > 5:
|
||||
if len(context.scene.BIMProjectProperties.clipping_planes) > 5:
|
||||
self.report({"INFO"}, "Maximum of six clipping planes allowed.")
|
||||
return {"FINISHED"}
|
||||
|
||||
for area in bpy.context.screen.areas:
|
||||
for area in context.screen.areas:
|
||||
if area.type == "VIEW_3D":
|
||||
area.tag_redraw()
|
||||
|
||||
region = context.region
|
||||
rv3d = context.region_data
|
||||
coord = (self.mouse_x, self.mouse_y)
|
||||
origin = region_2d_to_origin_3d(region, rv3d, coord)
|
||||
direction = region_2d_to_vector_3d(region, rv3d, coord)
|
||||
hit, location, normal, face_index, obj, matrix = self.ray_cast(context, origin, direction)
|
||||
if not hit:
|
||||
self.report({"INFO"}, "No object found.")
|
||||
return {"FINISHED"}
|
||||
if rv3d: # Called from a 3D viewport
|
||||
coord = (self.mouse_x, self.mouse_y)
|
||||
origin = region_2d_to_origin_3d(region, rv3d, coord)
|
||||
direction = region_2d_to_vector_3d(region, rv3d, coord)
|
||||
hit, location, normal, face_index, obj, matrix = self.ray_cast(context, origin, direction)
|
||||
if not hit:
|
||||
self.report({"INFO"}, "No object found.")
|
||||
return {"FINISHED"}
|
||||
else: # Not Called from a 3D viewport
|
||||
location = (0, 0, 1)
|
||||
normal = (0, 0, 1)
|
||||
|
||||
vertices = [(-0.5, -0.5, 0), (0.5, -0.5, 0), (0.5, 0.5, 0), (-0.5, 0.5, 0)]
|
||||
|
||||
@@ -1956,20 +1956,20 @@ class CreateClippingPlane(bpy.types.Operator):
|
||||
mesh.update()
|
||||
|
||||
plane_obj = bpy.data.objects.new("ClippingPlane", mesh)
|
||||
bpy.context.collection.objects.link(plane_obj)
|
||||
context.collection.objects.link(plane_obj)
|
||||
z_axis = Vector((0, 0, 1))
|
||||
rotation_matrix = z_axis.rotation_difference(normal).to_matrix().to_4x4()
|
||||
plane_obj.matrix_world = rotation_matrix
|
||||
plane_obj.matrix_world.translation = location
|
||||
|
||||
bpy.context.scene.cursor.location = location
|
||||
context.scene.cursor.location = location
|
||||
|
||||
new = bpy.context.scene.BIMProjectProperties.clipping_planes.add()
|
||||
new = context.scene.BIMProjectProperties.clipping_planes.add()
|
||||
new.obj = plane_obj
|
||||
|
||||
tool.Blender.set_active_object(plane_obj)
|
||||
|
||||
ClippingPlaneDecorator.install(bpy.context)
|
||||
ClippingPlaneDecorator.install(context)
|
||||
bpy.ops.bim.refresh_clipping_planes("INVOKE_DEFAULT")
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -1991,11 +1991,11 @@ class FlipClippingPlane(bpy.types.Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.area.type == "VIEW_3D"
|
||||
return context.active_object
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.context.active_object
|
||||
if obj in [cp.obj for cp in bpy.context.scene.BIMProjectProperties.clipping_planes]:
|
||||
obj = context.active_object
|
||||
if obj in context.scene.BIMProjectProperties.clipping_planes_objs:
|
||||
obj.rotation_euler[0] += radians(180)
|
||||
bpy.context.view_layer.update()
|
||||
context.view_layer.update()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -187,6 +187,11 @@ class BIMProjectProperties(PropertyGroup):
|
||||
use_relative_project_path: BoolProperty(name="Use Relative Project Path", default=False)
|
||||
queried_obj: bpy.props.PointerProperty(type=bpy.types.Object)
|
||||
clipping_planes: bpy.props.CollectionProperty(type=ObjProperty)
|
||||
clipping_planes_active: bpy.props.IntProperty(min=0, default=0, max=5)
|
||||
|
||||
@property
|
||||
def clipping_planes_objs(self):
|
||||
return list({cp.obj for cp in self.clipping_planes if cp.obj})
|
||||
|
||||
def get_library_element_index(self, lib_element):
|
||||
return next((i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element))
|
||||
|
||||
@@ -936,6 +936,31 @@ class BIM_OT_enum_property_search(bpy.types.Operator):
|
||||
)
|
||||
|
||||
|
||||
class BIM_OT_select_object(bpy.types.Operator):
|
||||
bl_idname = "bim.select_object"
|
||||
bl_label = "Select Object"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj_name: bpy.props.StringProperty(description="Object Name To Select")
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects[self.obj_name]
|
||||
tool.Blender.set_objects_selection(context, obj, [obj], clear_previous_selection=True)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class BIM_OT_delete_object(bpy.types.Operator):
|
||||
bl_idname = "bim.delete_object"
|
||||
bl_label = "Delete Object"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj_name: bpy.props.StringProperty(description="Object Name To Delete")
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects[self.obj_name]
|
||||
with context.temp_override(selected_objects=[obj], active_object=obj):
|
||||
bpy.ops.bim.override_object_delete(is_batch=False)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditBlenderCollection(bpy.types.Operator):
|
||||
bl_idname = "bim.edit_blender_collection"
|
||||
bl_label = "Add or Remove Blender Collection Item"
|
||||
|
||||
@@ -127,6 +127,40 @@ class BIM_PT_section_with_cappings(Panel):
|
||||
row.operator("bim.clipping_plane_cut_with_cappings", icon="XRAY", text="Cut")
|
||||
row.operator("bim.revert_clipping_plane_cut", icon="FILE_REFRESH", text="Revert Cut")
|
||||
|
||||
props = context.scene.BIMProjectProperties
|
||||
box = layout.box()
|
||||
header = box.row(align=True)
|
||||
header.label(text="Clipping Planes")
|
||||
header.operator("bim.create_clipping_plane", text="", icon="ADD")
|
||||
|
||||
box.template_list(
|
||||
"BIM_UL_clipping_plane",
|
||||
"",
|
||||
props,
|
||||
"clipping_planes",
|
||||
props,
|
||||
"clipping_planes_active",
|
||||
)
|
||||
|
||||
if props.clipping_planes_active < len(props.clipping_planes):
|
||||
active_clipping_plane_obj = props.clipping_planes[props.clipping_planes_active].obj
|
||||
box.prop(active_clipping_plane_obj, "location")
|
||||
box.prop(active_clipping_plane_obj, "rotation_euler")
|
||||
|
||||
|
||||
class BIM_UL_clipping_plane(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
obj = item.obj
|
||||
row = layout.row(align=True)
|
||||
row.prop(obj, "name", text="", emboss=False)
|
||||
row.operator("bim.select_object", text="", icon="RESTRICT_SELECT_OFF").obj_name = obj.name
|
||||
row.context_pointer_set("active_object", obj)
|
||||
row.operator("bim.flip_clipping_plane", text="", icon="PASTEFLIPDOWN")
|
||||
row.operator("bim.delete_object", text="", icon="TRASH").obj_name = obj.name
|
||||
else:
|
||||
layout.label(text="", translate=False)
|
||||
|
||||
|
||||
class BIM_UL_generic(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
|
||||
@@ -689,6 +689,14 @@ class Blender(blenderbim.core.tool.Blender):
|
||||
|
||||
return collections_mapping
|
||||
|
||||
@classmethod
|
||||
def object_supports_edit_mode(cls, obj):
|
||||
if not obj.data:
|
||||
return False, "Can't Edit Empty Object"
|
||||
if obj in bpy.context.scene.BIMProjectProperties.clipping_planes_objs:
|
||||
return False, "Can't Edit Clipping Plane Geometry"
|
||||
return True, ""
|
||||
|
||||
class Modifier:
|
||||
@classmethod
|
||||
def is_eligible_for_railing_modifier(cls, obj):
|
||||
@@ -790,8 +798,7 @@ class Blender(blenderbim.core.tool.Blender):
|
||||
@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
|
||||
yield from json.loads(array_pset["Data"])
|
||||
|
||||
@classmethod
|
||||
def get_children_objects(cls, modifier_data):
|
||||
@@ -838,7 +845,9 @@ class Blender(blenderbim.core.tool.Blender):
|
||||
bpy.utils.register_tool(ws_model.PipeTool, after={"bim.duct_tool"}, separator=False, group=False)
|
||||
bpy.utils.register_tool(ws_model.BimTool, after={"bim.pipe_tool"}, separator=False, group=False)
|
||||
bpy.utils.register_tool(ws_drawing.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=False)
|
||||
bpy.utils.register_tool(ws_spatial.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=False)
|
||||
bpy.utils.register_tool(
|
||||
ws_spatial.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=False
|
||||
)
|
||||
bpy.utils.register_tool(
|
||||
ws_structural.StructuralTool, after={"bim.spatial_tool"}, separator=False, group=False
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user