mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
You can now edit arbitrary profiles in the profile manager
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.module.type.prop as type_prop
|
||||
from bpy.types import WorkSpaceTool
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
@@ -51,9 +52,14 @@ class CadTool(WorkSpaceTool):
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_Q")
|
||||
row.operator("bim.edit_extrusion_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_extrusion_profile", text="", icon="CANCEL")
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
row.operator("bim.edit_extrusion_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_extrusion_profile", text="", icon="CANCEL")
|
||||
else:
|
||||
row.operator("bim.edit_arbitrary_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_arbitrary_profile", text="", icon="CANCEL")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
@@ -180,7 +186,10 @@ class CadHotkey(bpy.types.Operator):
|
||||
bpy.ops.bim.cad_offset(distance=self.props.distance)
|
||||
|
||||
def hotkey_S_Q(self):
|
||||
bpy.ops.bim.edit_extrusion_profile()
|
||||
if tool.Ifc.get_entity(bpy.context.active_object):
|
||||
bpy.ops.bim.edit_extrusion_profile()
|
||||
else:
|
||||
bpy.ops.bim.edit_arbitrary_profile()
|
||||
|
||||
def hotkey_S_R(self):
|
||||
if self.is_profile():
|
||||
|
||||
@@ -173,10 +173,9 @@ class DumbSlabGenerator:
|
||||
matrix_world[2][3] = self.collection_obj.location[2] - self.depth
|
||||
else:
|
||||
matrix_world[2][3] -= self.depth
|
||||
obj.matrix_world = matrix_world
|
||||
obj.matrix_world = Matrix.Rotation(self.x_angle, 4, 'X') @ matrix_world
|
||||
bpy.context.view_layer.update()
|
||||
self.collection.objects.link(obj)
|
||||
obj.matrix_world = Matrix.Rotation(self.x_angle, 4, 'X')
|
||||
|
||||
element = blenderbim.core.root.assign_class(
|
||||
tool.Ifc,
|
||||
@@ -618,122 +617,13 @@ class EnableEditingExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
else:
|
||||
position = Matrix()
|
||||
|
||||
self.vertices = []
|
||||
self.edges = []
|
||||
self.arcs = []
|
||||
self.circles = []
|
||||
|
||||
profile = extrusion.SweptArea
|
||||
if profile.is_a("IfcArbitraryClosedProfileDef"):
|
||||
self.process_curve(obj, position, profile.OuterCurve)
|
||||
if profile.is_a("IfcArbitraryProfileDefWithVoids"):
|
||||
for inner_curve in profile.InnerCurves:
|
||||
self.process_curve(obj, position, inner_curve)
|
||||
elif profile.is_a() == "IfcRectangleProfileDef":
|
||||
self.process_rectangle(obj, position, profile)
|
||||
|
||||
mesh = bpy.data.meshes.new("Profile")
|
||||
mesh.from_pydata(self.vertices, self.edges, [])
|
||||
mesh.BIMMeshProperties.is_profile = True
|
||||
obj.data = mesh
|
||||
|
||||
for arc in self.arcs:
|
||||
group = obj.vertex_groups.new(name="IFCARCINDEX")
|
||||
group.add(arc, 1, "REPLACE")
|
||||
|
||||
for circle in self.circles:
|
||||
group = obj.vertex_groups.new(name="IFCCIRCLE")
|
||||
group.add(circle, 1, "REPLACE")
|
||||
tool.Model.import_profile(extrusion.SweptArea, obj=obj, position=position)
|
||||
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
DecorationsHandler.install(context)
|
||||
bpy.ops.wm.tool_set_by_id(name="bim.cad_tool")
|
||||
return {"FINISHED"}
|
||||
|
||||
def process_curve(self, obj, position, curve):
|
||||
offset = len(self.vertices)
|
||||
|
||||
if curve.is_a("IfcPolyline"):
|
||||
total_points = len(curve.Points)
|
||||
last_index = len(curve.Points) - 1
|
||||
for i, point in enumerate(curve.Points):
|
||||
if i == last_index:
|
||||
continue
|
||||
global_point = position @ Vector(self.convert_unit_to_si(point.Coordinates)).to_3d()
|
||||
self.vertices.append(global_point)
|
||||
self.edges.extend([(i, i + 1) for i in range(offset, len(self.vertices))])
|
||||
self.edges[-1] = (len(self.vertices) - 1, offset) # Close the loop
|
||||
elif curve.is_a("IfcIndexedPolyCurve"):
|
||||
is_arc = False
|
||||
if curve.Segments:
|
||||
for segment in curve.Segments:
|
||||
if len(segment[0]) == 3: # IfcArcIndex
|
||||
is_arc = True
|
||||
local_point = self.convert_unit_to_si(curve.Points.CoordList[segment[0][0] - 1])
|
||||
global_point = position @ Vector(local_point).to_3d()
|
||||
self.vertices.append(global_point)
|
||||
local_point = self.convert_unit_to_si(curve.Points.CoordList[segment[0][1] - 1])
|
||||
global_point = position @ Vector(local_point).to_3d()
|
||||
self.vertices.append(global_point)
|
||||
self.arcs.append([len(self.vertices) - 2, len(self.vertices) - 1])
|
||||
else:
|
||||
local_point = self.convert_unit_to_si(curve.Points.CoordList[segment[0][0] - 1])
|
||||
global_point = position @ Vector(local_point).to_3d()
|
||||
self.vertices.append(global_point)
|
||||
if is_arc:
|
||||
self.arcs[-1].append(len(self.vertices) - 1)
|
||||
is_arc = False
|
||||
else:
|
||||
for local_point in curve.Points.CoordList:
|
||||
global_point = position @ Vector(self.convert_unit_to_si(local_point)).to_3d()
|
||||
self.vertices.append(global_point)
|
||||
# Curves without segments are self closing
|
||||
del self.vertices[-1]
|
||||
|
||||
self.edges.extend([(i, i + 1) for i in range(offset, len(self.vertices))])
|
||||
self.edges[-1] = (len(self.vertices) - 1, offset) # Close the loop
|
||||
elif curve.is_a("IfcCircle"):
|
||||
center = self.convert_unit_to_si(
|
||||
Matrix(ifcopenshell.util.placement.get_axis2placement(curve.Position).tolist()).col[3].to_3d()
|
||||
)
|
||||
radius = self.convert_unit_to_si(curve.Radius)
|
||||
self.vertices.extend(
|
||||
[
|
||||
position @ Vector((center[0], center[1] - curve.Radius, 0.0)),
|
||||
position @ Vector((center[0], center[1] + curve.Radius, 0.0)),
|
||||
]
|
||||
)
|
||||
self.circles.append([offset, offset + 1])
|
||||
self.edges.append((offset, offset + 1))
|
||||
|
||||
def process_rectangle(self, obj, position, profile):
|
||||
if profile.Position:
|
||||
p_position = Matrix(ifcopenshell.util.placement.get_axis2placement(profile.Position).tolist())
|
||||
p_position[0][3] *= self.unit_scale
|
||||
p_position[1][3] *= self.unit_scale
|
||||
p_position[2][3] *= self.unit_scale
|
||||
else:
|
||||
p_position = Matrix()
|
||||
|
||||
x = self.convert_unit_to_si(profile.XDim)
|
||||
y = self.convert_unit_to_si(profile.YDim)
|
||||
|
||||
self.vertices.extend(
|
||||
[
|
||||
position @ p_position @ Vector((-x / 2, -y / 2, 0.0)),
|
||||
position @ p_position @ Vector((x / 2, -y / 2, 0.0)),
|
||||
position @ p_position @ Vector((x / 2, y / 2, 0.0)),
|
||||
position @ p_position @ Vector((-x / 2, y / 2, 0.0)),
|
||||
]
|
||||
)
|
||||
self.edges.extend([(i, i + 1) for i in range(0, len(self.vertices))])
|
||||
self.edges[-1] = (len(self.vertices) - 1, 0) # Close the loop
|
||||
|
||||
def convert_unit_to_si(self, value):
|
||||
if isinstance(value, (tuple, list)):
|
||||
return [v * self.unit_scale for v in value]
|
||||
return value * self.unit_scale
|
||||
|
||||
|
||||
class EditExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_extrusion_profile"
|
||||
@@ -758,40 +648,16 @@ class EditExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
else:
|
||||
position = Matrix()
|
||||
|
||||
helper = Helper(tool.Ifc.get())
|
||||
indices = helper.auto_detect_arbitrary_profile_with_voids(obj, obj.data)
|
||||
|
||||
if isinstance(indices, tuple) and indices[0] is False: # Ugly
|
||||
profile = tool.Model.export_profile(obj, position=position)
|
||||
|
||||
if not profile:
|
||||
def msg(self, context):
|
||||
self.layout.label(text="INVALID PROFILE: " + indices[1])
|
||||
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
DecorationsHandler.install(context)
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
return {"FINISHED"}
|
||||
|
||||
self.bm = bmesh.new()
|
||||
self.bm.from_mesh(obj.data)
|
||||
self.bm.verts.ensure_lookup_table()
|
||||
self.bm.edges.ensure_lookup_table()
|
||||
|
||||
if indices["inner_curves"]:
|
||||
profile = tool.Ifc.get().createIfcArbitraryProfileDefWithVoids("AREA")
|
||||
else:
|
||||
profile = tool.Ifc.get().createIfcArbitraryClosedProfileDef("AREA")
|
||||
|
||||
if tool.Ifc.get().schema != "IFC2X3":
|
||||
self.points = self.create_points(position, indices["points"])
|
||||
|
||||
profile.OuterCurve = self.create_curve(position, indices["profile"])
|
||||
if indices["inner_curves"]:
|
||||
results = []
|
||||
for inner_curve in indices["inner_curves"]:
|
||||
results.append(self.create_curve(position, inner_curve))
|
||||
profile.InnerCurves = results
|
||||
|
||||
self.bm.free()
|
||||
return
|
||||
|
||||
old_profile = extrusion.SweptArea
|
||||
extrusion.SweptArea = profile
|
||||
@@ -831,45 +697,6 @@ class EditExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
return {"FINISHED"}
|
||||
|
||||
def create_points(self, position, indices):
|
||||
position_i = position.inverted()
|
||||
points = []
|
||||
for point in indices:
|
||||
local_point = (position_i @ point).to_2d()
|
||||
points.append(self.convert_si_to_unit(list(local_point)))
|
||||
return tool.Ifc.get().createIfcCartesianPointList2D(points)
|
||||
|
||||
def create_curve(self, position, edge_indices, points=None):
|
||||
position_i = position.inverted()
|
||||
if len(edge_indices) == 2:
|
||||
diameter = edge_indices[0]
|
||||
p1 = self.bm.verts[diameter[0]].co
|
||||
p2 = self.bm.verts[diameter[1]].co
|
||||
center = self.convert_si_to_unit(list(position_i @ p1.lerp(p2, 0.5)))
|
||||
radius = self.convert_si_to_unit((p1 - p2).length / 2)
|
||||
return tool.Ifc.get().createIfcCircle(
|
||||
tool.Ifc.get().createIfcAxis2Placement2D(tool.Ifc.get().createIfcCartesianPoint(center[0:2])), radius
|
||||
)
|
||||
if tool.Ifc.get().schema == "IFC2X3":
|
||||
points = []
|
||||
for edge in edge_indices:
|
||||
local_point = (position_i @ Vector(self.bm.verts[edge[0]].co)).to_2d()
|
||||
points.append(tool.Ifc.get().createIfcCartesianPoint(self.convert_si_to_unit(local_point)))
|
||||
points.append(points[0])
|
||||
return tool.Ifc.get().createIfcPolyline(points)
|
||||
segments = []
|
||||
for segment in edge_indices:
|
||||
if len(segment) == 2:
|
||||
segments.append(tool.Ifc.get().createIfcLineIndex([i + 1 for i in segment]))
|
||||
elif len(segment) == 3:
|
||||
segments.append(tool.Ifc.get().createIfcArcIndex([i + 1 for i in segment]))
|
||||
return tool.Ifc.get().createIfcIndexedPolyCurve(self.points, segments, False)
|
||||
|
||||
def convert_si_to_unit(self, value):
|
||||
if isinstance(value, (tuple, list)):
|
||||
return [v / self.unit_scale for v in value]
|
||||
return value / self.unit_scale
|
||||
|
||||
|
||||
class ResetVertex(bpy.types.Operator):
|
||||
bl_idname = "bim.reset_vertex"
|
||||
|
||||
@@ -413,7 +413,9 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.ops.bim.align_product(align_type="CENTERLINE")
|
||||
|
||||
def hotkey_S_E(self):
|
||||
if self.active_class in ("IfcWall", "IfcWallStandardCase"):
|
||||
if not bpy.context.selected_objects:
|
||||
return
|
||||
elif self.active_class in ("IfcWall", "IfcWallStandardCase"):
|
||||
bpy.ops.bim.join_wall(join_type="T")
|
||||
elif self.active_class in ("IfcSlab", "IfcSlabStandardCase", "IfcRamp", "IfcRoof"):
|
||||
if not bpy.context.active_object:
|
||||
|
||||
@@ -21,9 +21,12 @@ from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.AddProfileDef,
|
||||
operator.DisableEditingArbitraryProfile,
|
||||
operator.DisableEditingProfile,
|
||||
operator.DisableProfileEditingUI,
|
||||
operator.EditArbitraryProfile,
|
||||
operator.EditProfile,
|
||||
operator.EnableEditingArbitraryProfile,
|
||||
operator.EnableEditingProfile,
|
||||
operator.LoadProfiles,
|
||||
operator.RemoveProfileDef,
|
||||
|
||||
@@ -31,7 +31,12 @@ class ProfileData:
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {"total_profiles": cls.total_profiles(), "profile_classes": cls.profile_classes()}
|
||||
cls.data = {
|
||||
"total_profiles": cls.total_profiles(),
|
||||
"profile_classes": cls.profile_classes(),
|
||||
"is_arbitrary_profile": cls.is_arbitrary_profile(),
|
||||
"is_editing_arbitrary_profile": cls.is_editing_arbitrary_profile(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
@@ -52,3 +57,16 @@ class ProfileData:
|
||||
(c, c, ifcopenshell.util.doc.get_entity_doc(schema_identifier, c)["description"] or "")
|
||||
for c in sorted(classes)
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def is_arbitrary_profile(cls):
|
||||
props = bpy.context.scene.BIMProfileProperties
|
||||
if props.active_profile_id:
|
||||
profile = tool.Ifc.get().by_id(props.active_profile_id)
|
||||
if profile.is_a("IfcArbitraryClosedProfileDef"):
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def is_editing_arbitrary_profile(cls):
|
||||
obj = bpy.context.active_object
|
||||
return obj and obj.data and hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.is_profile
|
||||
|
||||
@@ -20,6 +20,7 @@ import bpy
|
||||
import ifcopenshell.api
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.module.model.slab import DecorationsHandler
|
||||
|
||||
|
||||
class LoadProfiles(bpy.types.Operator):
|
||||
@@ -35,6 +36,7 @@ class LoadProfiles(bpy.types.Operator):
|
||||
new = props.profiles.add()
|
||||
new.ifc_definition_id = profile.id()
|
||||
new.name = profile.ProfileName or "Unnamed"
|
||||
new.ifc_class = profile.is_a()
|
||||
|
||||
props.is_editing = True
|
||||
bpy.ops.bim.disable_editing_profile()
|
||||
@@ -60,21 +62,19 @@ class RemoveProfileDef(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def _execute(self, context):
|
||||
ifcopenshell.api.run("profile.remove_profile", tool.Ifc.get(), profile=tool.Ifc.get().by_id(self.profile))
|
||||
bpy.ops.bim.load_profiles()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingProfile(bpy.types.Operator):
|
||||
class EnableEditingProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.enable_editing_profile"
|
||||
bl_label = "Enable Editing Profile"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
profile: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMProfileProperties
|
||||
props.profile_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.profile), props.profile_attributes)
|
||||
props.active_profile_id = self.profile
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingProfile(bpy.types.Operator):
|
||||
@@ -98,7 +98,6 @@ class EditProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
profile = tool.Ifc.get().by_id(props.active_profile_id)
|
||||
ifcopenshell.api.run("profile.edit_profile", tool.Ifc.get(), profile=profile, attributes=attributes)
|
||||
bpy.ops.bim.load_profiles()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddProfileDef(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -110,9 +109,69 @@ class AddProfileDef(bpy.types.Operator, tool.Ifc.Operator):
|
||||
props = context.scene.BIMProfileProperties
|
||||
profile_class = props.profile_classes
|
||||
if profile_class == "IfcArbitraryClosedProfileDef":
|
||||
points = [(0, 0), (0.1, 0), (0.1, 0.1), (0, 0.1)]
|
||||
ifcopenshell.api.run("profile.add_arbitrary_profile", tool.Ifc.get(), profile=points)
|
||||
points = [(0, 0), (0.1, 0), (0.1, 0.1), (0, 0.1), (0, 0)]
|
||||
profile = ifcopenshell.api.run("profile.add_arbitrary_profile", tool.Ifc.get(), profile=points)
|
||||
else:
|
||||
ifcopenshell.api.run("profile.add_parameterized_profile", tool.Ifc.get(), ifc_class=profile_class)
|
||||
profile = ifcopenshell.api.run("profile.add_parameterized_profile", tool.Ifc.get(), ifc_class=profile_class)
|
||||
profile.ProfileName = "New Profile"
|
||||
bpy.ops.bim.load_profiles()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingArbitraryProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.enable_editing_arbitrary_profile"
|
||||
bl_label = "Enable Editing Arbitrary Profile"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMProfileProperties
|
||||
profile = tool.Ifc.get().by_id(props.active_profile_id)
|
||||
obj = tool.Model.import_profile(profile)
|
||||
bpy.context.scene.collection.objects.link(obj)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
DecorationsHandler.install(context)
|
||||
bpy.ops.wm.tool_set_by_id(name="bim.cad_tool")
|
||||
|
||||
|
||||
class DisableEditingArbitraryProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.disable_editing_arbitrary_profile"
|
||||
bl_label = "Disable Editing Arbitrary Profile"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
DecorationsHandler.uninstall()
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
bpy.data.objects.remove(obj)
|
||||
|
||||
|
||||
class EditArbitraryProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_arbitrary_profile"
|
||||
bl_label = "Edit Arbitrary Profile"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMProfileProperties
|
||||
old_profile = tool.Ifc.get().by_id(props.active_profile_id)
|
||||
|
||||
obj = context.active_object
|
||||
|
||||
DecorationsHandler.uninstall()
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
|
||||
profile = tool.Model.export_profile(obj)
|
||||
if not profile:
|
||||
def msg(self, context):
|
||||
self.layout.label(text="INVALID PROFILE: " + indices[1])
|
||||
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
DecorationsHandler.install(context)
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
return
|
||||
|
||||
bpy.data.objects.remove(obj)
|
||||
profile.ProfileType = old_profile.ProfileType
|
||||
profile.ProfileName = old_profile.ProfileName
|
||||
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_profile)
|
||||
bpy.ops.bim.load_profiles()
|
||||
props.active_profile_id = profile.id()
|
||||
|
||||
@@ -44,6 +44,7 @@ def get_profile_classes(self, context):
|
||||
|
||||
class Profile(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_class: StringProperty(name="IFC Class")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
|
||||
|
||||
@@ -67,6 +67,14 @@ class BIM_PT_profiles(Panel):
|
||||
self.draw_editable_ui(context)
|
||||
|
||||
def draw_editable_ui(self, context):
|
||||
if ProfileData.data["is_arbitrary_profile"]:
|
||||
if ProfileData.data["is_editing_arbitrary_profile"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.edit_arbitrary_profile", text="Save Profile", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_arbitrary_profile", text="", icon="CANCEL")
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.operator("bim.enable_editing_arbitrary_profile", text="Edit Profile", icon="GREASEPENCIL")
|
||||
blenderbim.bim.helper.draw_attributes(self.props.profile_attributes, self.layout)
|
||||
|
||||
|
||||
@@ -76,6 +84,7 @@ class BIM_UL_profiles(UIList):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name or "Unnamed")
|
||||
row.label(text=item.ifc_class)
|
||||
|
||||
if props.active_profile_id == item.ifc_definition_id:
|
||||
row.operator("bim.edit_profile", text="", icon="CHECKMARK")
|
||||
|
||||
@@ -42,8 +42,8 @@ IfcOpenShell (using an IfcOpenBot build) for convenience. Instructions on how to
|
||||
compile IfcOpenShell is out of scope of this document.
|
||||
|
||||
You can create your own package by using the Makefile as shown below. You can
|
||||
choose between a ``PLATFORM`` of ``linux``, ``macos``, and ``win``. You can
|
||||
choose between a ``PYVERSION`` of ``py39``, ``py37``, or ``py310``.
|
||||
choose between a ``PLATFORM`` of ``linux``, ``macos``, ``macosm1``, and ``win``.
|
||||
You can choose between a ``PYVERSION`` of ``py39``, ``py37``, or ``py310``.
|
||||
::
|
||||
|
||||
$ cd src/blenderbim
|
||||
|
||||
Reference in New Issue
Block a user