mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 10:33:20 +00:00
Added "IFC Stair" to object modifiers
1) Added "IFC Stair" to object modifiers - it works in similar way as "IFC Array". It creates a stair from current object (if it's IfcStairFlight) and writes it's parameters to property set "BBIM_Stair" and also to IfcStairFlight parameters. Then you can edit it - modifying stair parameters and immediately see the changes, then you can save those changes or discard them. 2) "Clever Stair" operator (in Shift+A menu) works a bit different now - it creates new IfcStairFlight with IFC Stair modifier activated.
This commit is contained in:
@@ -73,8 +73,10 @@ classes = (
|
||||
prop.ConstrBrowserState,
|
||||
prop.BIMModelProperties,
|
||||
prop.BIMArrayProperties,
|
||||
prop.BIMStairProperties,
|
||||
ui.BIM_PT_authoring,
|
||||
ui.BIM_PT_array,
|
||||
ui.BIM_PT_stair,
|
||||
ui.DisplayConstrTypesUI,
|
||||
ui.LaunchTypeManager,
|
||||
ui.HelpConstrTypes,
|
||||
@@ -82,6 +84,11 @@ classes = (
|
||||
grid.BIM_OT_add_object,
|
||||
stair.BIM_OT_add_object,
|
||||
stair.BIM_OT_add_clever_stair,
|
||||
stair.AddStair,
|
||||
stair.CancelEditingStair,
|
||||
stair.FinishEditingStair,
|
||||
stair.EnableEditingStair,
|
||||
stair.RemoveStair,
|
||||
pie.OpenPieClass,
|
||||
pie.PieUpdateContainer,
|
||||
pie.PieAddOpening,
|
||||
@@ -97,6 +104,7 @@ def register():
|
||||
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.Object.BIMArrayProperties = bpy.props.PointerProperty(type=prop.BIMArrayProperties)
|
||||
bpy.types.Object.BIMStairProperties = bpy.props.PointerProperty(type=prop.BIMStairProperties)
|
||||
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_add.append(ui.add_menu)
|
||||
@@ -114,6 +122,7 @@ def unregister():
|
||||
bpy.utils.unregister_tool(workspace.BimTool)
|
||||
del bpy.types.Scene.BIMModelProperties
|
||||
del bpy.types.Object.BIMArrayProperties
|
||||
del bpy.types.Object.BIMStairProperties
|
||||
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(stair.add_object_button)
|
||||
|
||||
@@ -27,9 +27,11 @@ import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound
|
||||
|
||||
|
||||
def refresh():
|
||||
AuthoringData.is_loaded = False
|
||||
ArrayData.is_loaded = False
|
||||
StairData.is_loaded = False
|
||||
|
||||
|
||||
class AuthoringData:
|
||||
@@ -352,3 +354,23 @@ class ArrayData:
|
||||
except:
|
||||
parameters["has_parent"] = False
|
||||
return parameters
|
||||
|
||||
|
||||
class StairData:
|
||||
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_Stair", None)
|
||||
if parameters:
|
||||
parameters["data"] = json.loads(parameters.get("Data", "[]") or "[]")
|
||||
return parameters
|
||||
|
||||
@@ -228,8 +228,8 @@ class BIMModelProperties(PropertyGroup):
|
||||
x: bpy.props.FloatProperty(name="X", default=0.5)
|
||||
y: bpy.props.FloatProperty(name="Y", default=0.5)
|
||||
z: bpy.props.FloatProperty(name="Z", default=0.5)
|
||||
rl1: bpy.props.FloatProperty(name="RL", default=1) # Used for things like walls, doors, flooring, skirting, etc
|
||||
rl2: bpy.props.FloatProperty(name="RL", default=1) # Used for things like windows, other hosted furniture
|
||||
rl1: bpy.props.FloatProperty(name="RL", default=1) # Used for things like walls, doors, flooring, skirting, etc
|
||||
rl2: bpy.props.FloatProperty(name="RL", default=1) # Used for things like windows, other hosted furniture
|
||||
x_angle: bpy.props.FloatProperty(name="X Angle", default=0)
|
||||
type_page: bpy.props.IntProperty(name="Type Page", default=1, update=update_type_page)
|
||||
type_template: bpy.props.EnumProperty(
|
||||
@@ -253,3 +253,28 @@ class BIMArrayProperties(PropertyGroup):
|
||||
x: bpy.props.FloatProperty(name="X", default=0)
|
||||
y: bpy.props.FloatProperty(name="Y", default=0)
|
||||
z: bpy.props.FloatProperty(name="Z", default=0)
|
||||
|
||||
|
||||
class BIMStairProperties(PropertyGroup):
|
||||
is_editing: bpy.props.IntProperty(default=-1)
|
||||
width: bpy.props.FloatProperty(name="Width", default=1.2, soft_min=0.01)
|
||||
height: bpy.props.FloatProperty(name="Height", default=1.0, soft_min=0.01)
|
||||
number_of_treads: bpy.props.IntProperty(name="Number of Treads (Goings)", default=6, soft_min=1)
|
||||
tread_depth: bpy.props.FloatProperty(name="Tread Depth", default=0.25, soft_min=0.01)
|
||||
tread_run: bpy.props.FloatProperty(name="Tread Run", default=0.3, soft_min=0.01)
|
||||
base_slab_depth: bpy.props.FloatProperty(name="Base slab depth", default=0.25, soft_min=0)
|
||||
top_slab_depth: bpy.props.FloatProperty(name="Top slab depth", default=0.25, soft_min=0)
|
||||
has_top_nib: bpy.props.BoolProperty(name="Has top nib", default=True)
|
||||
|
||||
def get_props_kwargs(self):
|
||||
kwargs = {
|
||||
"width": self.width,
|
||||
"height": self.height,
|
||||
"number_of_treads": self.number_of_treads,
|
||||
"tread_depth": self.tread_depth,
|
||||
"tread_run": self.tread_run,
|
||||
"base_slab_depth": self.base_slab_depth,
|
||||
"top_slab_depth": self.top_slab_depth,
|
||||
"has_top_nib": self.has_top_nib,
|
||||
}
|
||||
return kwargs
|
||||
|
||||
@@ -20,18 +20,22 @@ import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.props import FloatProperty, IntProperty, BoolProperty
|
||||
from bpy_extras.object_utils import AddObjectHelper, object_data_add
|
||||
from mathutils import Vector
|
||||
|
||||
import bmesh
|
||||
from bmesh.types import BMVert
|
||||
|
||||
import ifcopenshell
|
||||
import blenderbim
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.module.model.prop import BIMStairProperties
|
||||
|
||||
|
||||
from mathutils import Vector
|
||||
from pprint import pprint
|
||||
import json
|
||||
|
||||
|
||||
def add_dumb_stair_object(self, context):
|
||||
if self.number_of_treads <= 0:
|
||||
self.number_of_treads = 1
|
||||
verts = [
|
||||
Vector((0, 0, 0)),
|
||||
Vector((0, self.tread_length, 0)),
|
||||
@@ -69,7 +73,7 @@ class BIM_OT_add_object(Operator, AddObjectHelper):
|
||||
width: FloatProperty(name="Width", default=1.1)
|
||||
height: FloatProperty(name="Height", default=1)
|
||||
tread_depth: FloatProperty(name="Tread Depth", default=0.2)
|
||||
number_of_treads: IntProperty(name="Number of Treads (Goings)", default=6)
|
||||
number_of_treads: IntProperty(name="Number of Treads (Goings)", default=6, soft_min=1)
|
||||
tread_length: FloatProperty(name="Tread Length (Going)", default=0.25)
|
||||
riser_height: FloatProperty(name="*Calculated* Riser Height")
|
||||
length: FloatProperty(name="*Calculated* Length")
|
||||
@@ -79,30 +83,25 @@ class BIM_OT_add_object(Operator, AddObjectHelper):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
def create_stair(
|
||||
operator,
|
||||
context,
|
||||
width=1.2,
|
||||
height=1.0,
|
||||
number_of_treads=6,
|
||||
tread_depth=0.25,
|
||||
tread_run=0.3,
|
||||
# tread_rise = None, # 0.167
|
||||
base_slab_depth=0.25,
|
||||
top_slab_depth=0.25,
|
||||
has_top_nib=False,
|
||||
def generate_stair_2d_profile(
|
||||
number_of_treads,
|
||||
height,
|
||||
width,
|
||||
tread_run,
|
||||
tread_depth,
|
||||
has_top_nib,
|
||||
top_slab_depth,
|
||||
base_slab_depth,
|
||||
stair_type="CONCRETE",
|
||||
extrude=True,
|
||||
):
|
||||
|
||||
vertices = []
|
||||
edges = []
|
||||
|
||||
# 2d profile generation
|
||||
tread_rise = height / number_of_treads
|
||||
length = tread_run * number_of_treads
|
||||
number_of_risers = number_of_treads + 1
|
||||
tread_rise = height / number_of_risers
|
||||
length = tread_run * number_of_risers
|
||||
|
||||
for i in range(number_of_treads):
|
||||
for i in range(number_of_risers):
|
||||
vertices.extend([
|
||||
Vector((tread_run*i, 0, tread_rise*i)),
|
||||
Vector((tread_run*i, 0, tread_rise*(i+1)))
|
||||
@@ -112,8 +111,8 @@ def create_stair(
|
||||
edges.append((cur_vertex - 1, cur_vertex))
|
||||
edges.append((cur_vertex, cur_vertex + 1))
|
||||
|
||||
vertices.append(Vector((tread_run * number_of_treads, 0, tread_rise * number_of_treads)))
|
||||
edges.append((number_of_treads * 2, number_of_treads * 2 - 1))
|
||||
vertices.append(Vector((tread_run * number_of_risers, 0, tread_rise * number_of_risers)))
|
||||
edges.append((number_of_risers * 2, number_of_risers * 2 - 1))
|
||||
|
||||
td_vector = Vector((vertices[2][2], 0, -vertices[2][0])).normalized() * tread_depth
|
||||
|
||||
@@ -127,15 +126,15 @@ def create_stair(
|
||||
|
||||
# top nib
|
||||
if has_top_nib:
|
||||
vertices.append( vertices[number_of_treads * 2] + Vector((0, 0, -top_slab_depth)) )
|
||||
vertices.append( vertices[number_of_treads * 2] + Vector(((-top_slab_depth - b) / k, 0, -top_slab_depth)) )
|
||||
vertices.append( vertices[number_of_risers * 2] + Vector((0, 0, -top_slab_depth)) )
|
||||
vertices.append( vertices[number_of_risers * 2] + Vector(((-top_slab_depth - b) / k, 0, -top_slab_depth)) )
|
||||
last_vertex_i = len(vertices) - 1
|
||||
edges.append( (number_of_treads * 2, last_vertex_i - 1) )
|
||||
edges.append( (number_of_risers * 2, last_vertex_i - 1) )
|
||||
edges.append( (last_vertex_i - 1, last_vertex_i) )
|
||||
else:
|
||||
vertices.append(vertices[number_of_treads * 2] + depth_vector)
|
||||
vertices.append(vertices[number_of_risers * 2] + depth_vector)
|
||||
last_vertex_i = len(vertices) - 1
|
||||
edges.append((number_of_treads * 2, last_vertex_i))
|
||||
edges.append((number_of_risers * 2, last_vertex_i))
|
||||
|
||||
top_nib_end = len(vertices) - 1
|
||||
|
||||
@@ -154,7 +153,17 @@ def create_stair(
|
||||
|
||||
edges.append( (bottom_nib_end, top_nib_end) )
|
||||
faces = [list(range(len(vertices)))]
|
||||
# profile generation finished
|
||||
|
||||
return (vertices, edges, faces)
|
||||
|
||||
|
||||
def update_stair_modifier(context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStairProperties
|
||||
|
||||
props_kwargs = props.get_props_kwargs()
|
||||
props_kwargs["stair_type"] = "CONCRETE"
|
||||
vertices, edges, faces = generate_stair_2d_profile(**props_kwargs)
|
||||
|
||||
obj = context.object
|
||||
bm = bmesh.new()
|
||||
@@ -168,49 +177,19 @@ def create_stair(
|
||||
|
||||
bmesh.ops.contextual_create(bm, geom=new_edges)
|
||||
|
||||
if extrude:
|
||||
bm.faces.ensure_lookup_table()
|
||||
faces = [bm.faces[0]]
|
||||
extruded = bmesh.ops.extrude_face_region(bm, geom=faces)
|
||||
extrusion_vector = Vector((0, 1, 0)) * width
|
||||
translate_verts = [v for v in extruded["geom"] if isinstance(v, BMVert)]
|
||||
bmesh.ops.translate(bm, vec=extrusion_vector, verts=translate_verts)
|
||||
|
||||
# set origin
|
||||
prev_cursor_location = bpy.context.scene.cursor.location.copy()
|
||||
bpy.context.scene.cursor.location = vertices[0]
|
||||
bpy.ops.object.origin_set(type="ORIGIN_CURSOR", center="MEDIAN")
|
||||
bpy.context.scene.cursor.location = prev_cursor_location
|
||||
bm.faces.ensure_lookup_table()
|
||||
faces = [bm.faces[0]]
|
||||
extruded = bmesh.ops.extrude_face_region(bm, geom=faces)
|
||||
extrusion_vector = Vector((0, 1, 0)) * props.width
|
||||
translate_verts = [v for v in extruded["geom"] if isinstance(v, BMVert)]
|
||||
bmesh.ops.translate(bm, vec=extrusion_vector, verts=translate_verts)
|
||||
|
||||
if context.object.mode == "EDIT":
|
||||
bmesh.update_edit_mesh(obj.data)
|
||||
else:
|
||||
bm.to_mesh(obj.data)
|
||||
bm.free()
|
||||
|
||||
return (obj, tread_rise, length)
|
||||
|
||||
|
||||
def add_object_stair(self, context):
|
||||
if context.object is None:
|
||||
self.report({"ERROR"}, "Select object that will be transformed to a stair.")
|
||||
return
|
||||
|
||||
mesh, tread_rise, length = create_stair(
|
||||
operator=self,
|
||||
context=context,
|
||||
stair_type="CONCRETE",
|
||||
width=self.width,
|
||||
height=self.height,
|
||||
number_of_treads=self.number_of_treads,
|
||||
tread_depth=self.tread_depth,
|
||||
tread_run=self.tread_run,
|
||||
base_slab_depth=self.base_slab_depth,
|
||||
top_slab_depth=self.top_slab_depth,
|
||||
has_top_nib=self.has_top_nib,
|
||||
)
|
||||
self.tread_rise = tread_rise
|
||||
self.length = length
|
||||
obj.data.update()
|
||||
|
||||
|
||||
class BIM_OT_add_clever_stair(Operator):
|
||||
@@ -218,20 +197,164 @@ class BIM_OT_add_clever_stair(Operator):
|
||||
bl_label = "Clever Stair"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
width: FloatProperty(name="Width", default=1.2, soft_min=0.01)
|
||||
height: FloatProperty(name="Height", default=1.0, soft_min=0.01)
|
||||
number_of_treads: IntProperty(name="Number of Treads (Goings)", default=6, soft_min=1)
|
||||
tread_depth: FloatProperty(name="Tread Depth", default=0.25, soft_min=0.01)
|
||||
tread_run: FloatProperty(name="Tread Run", default=0.3, soft_min=0.01)
|
||||
base_slab_depth: FloatProperty(name="Base slab depth", default=0.25, soft_min=0)
|
||||
top_slab_depth: FloatProperty(name="Top slab depth", default=0.25, soft_min=0)
|
||||
has_top_nib: BoolProperty(name="Has top nib", default=True)
|
||||
|
||||
tread_rise: FloatProperty(name="*Calculated* Tread Rise")
|
||||
length: FloatProperty(name="*Calculated* Length")
|
||||
|
||||
def execute(self, context):
|
||||
add_object_stair(self, context)
|
||||
ifcfile = tool.Ifc.get()
|
||||
if not ifcfile:
|
||||
self.report({"ERROR"}, "You need to start IFC project first to create a stair.")
|
||||
return {"CANCELLED"}
|
||||
|
||||
if context.object is not None:
|
||||
spawn_location = context.object.location.copy()
|
||||
context.object.select_set(False)
|
||||
else:
|
||||
spawn_location = bpy.context.scene.cursor.location.copy()
|
||||
|
||||
mesh = bpy.data.meshes.new("StairFlight")
|
||||
obj = bpy.data.objects.new("StairFlight", mesh)
|
||||
bpy.context.scene.collection.objects.link(obj)
|
||||
obj.location = spawn_location
|
||||
body_context = ifcopenshell.util.representation.get_context(ifcfile, "Model", "Body", "MODEL_VIEW")
|
||||
element = blenderbim.core.root.assign_class(
|
||||
tool.Ifc,
|
||||
tool.Collector,
|
||||
tool.Root,
|
||||
obj=obj,
|
||||
ifc_class="IfcStairFlight",
|
||||
should_add_representation=True,
|
||||
context=body_context,
|
||||
)
|
||||
bpy.context.view_layer.objects.active = None
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
bpy.ops.bim.add_stair()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
# UI operators
|
||||
class AddStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_stair"
|
||||
bl_label = "Add Stair"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
if not element.is_a("IfcStairFlight"):
|
||||
self.report({"ERROR"}, "Object has to be IfcStairFlight type to add a stair.")
|
||||
return {"CANCELLED"}
|
||||
|
||||
props = obj.BIMStairProperties
|
||||
|
||||
stair_data = props.get_props_kwargs()
|
||||
psets = ifcopenshell.util.element.get_psets(element)
|
||||
pset = psets.get("BBIM_Stair", None)
|
||||
|
||||
if pset:
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
else:
|
||||
pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="BBIM_Stair")
|
||||
|
||||
ifcopenshell.api.run(
|
||||
"pset.edit_pset",
|
||||
tool.Ifc.get(),
|
||||
pset=pset,
|
||||
properties={"Data": json.dumps(stair_data)},
|
||||
)
|
||||
update_stair_modifier(context)
|
||||
|
||||
# update IfcStairFlight properties
|
||||
element.NumberOfRisers = props.number_of_treads + 1
|
||||
element.NumberOfTreads = props.number_of_treads
|
||||
element.RiserHeight = props.height / element.NumberOfRisers
|
||||
element.TreadLength = props.tread_depth
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class CancelEditingStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.cancel_editing_stair"
|
||||
bl_label = "Cancel editing Stair"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
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_Stair"]["Data"])
|
||||
props = obj.BIMStairProperties
|
||||
# restore previous settings since editing was canceled
|
||||
for prop_name in data:
|
||||
setattr(props, prop_name, data[prop_name])
|
||||
update_stair_modifier(context)
|
||||
|
||||
props.is_editing = -1
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class FinishEditingStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.finish_editing_stair"
|
||||
bl_label = "Finish editing stair"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
props = obj.BIMStairProperties
|
||||
|
||||
psets = ifcopenshell.util.element.get_psets(element)
|
||||
pset = psets["BBIM_Stair"]
|
||||
data = props.get_props_kwargs()
|
||||
|
||||
props.is_editing = -1
|
||||
|
||||
update_stair_modifier(context)
|
||||
|
||||
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})
|
||||
|
||||
# update IfcStairFlight properties
|
||||
if element.is_a("IfcStairFlight"):
|
||||
element.NumberOfRisers = props.number_of_treads + 1
|
||||
element.NumberOfTreads = props.number_of_treads
|
||||
element.RiserHeight = props.height / element.NumberOfRisers
|
||||
element.TreadLength = props.tread_depth
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.enable_editing_stair"
|
||||
bl_label = "Enable Editing Stair"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStairProperties
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
pset = ifcopenshell.util.element.get_psets(element)
|
||||
data = json.loads(pset["BBIM_Stair"]["Data"])
|
||||
# required since we could load pset from .ifc and BIMStairProperties won't be set
|
||||
for prop_name in data:
|
||||
setattr(props, prop_name, data[prop_name])
|
||||
|
||||
props.is_editing = 1
|
||||
|
||||
|
||||
class RemoveStair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.remove_stair"
|
||||
bl_label = "Remove Stair"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
obj.BIMStairProperties.is_editing = -1
|
||||
|
||||
pset = ifcopenshell.util.element.get_psets(element)
|
||||
pset = tool.Ifc.get().by_id(pset["BBIM_Stair"]["id"])
|
||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
import bpy
|
||||
import blenderbim.tool as tool
|
||||
from bpy.types import Panel, Operator, Menu
|
||||
from blenderbim.bim.module.model.data import AuthoringData, ArrayData
|
||||
from blenderbim.bim.module.model.data import AuthoringData, ArrayData, StairData
|
||||
from blenderbim.bim.module.model.prop import store_cursor_position
|
||||
from blenderbim.bim.module.model.stair import update_stair_modifier
|
||||
|
||||
from blenderbim.bim.helper import prop_with_search
|
||||
|
||||
|
||||
@@ -291,6 +293,7 @@ class BIM_PT_array(bpy.types.Panel):
|
||||
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")
|
||||
@@ -306,6 +309,60 @@ class BIM_PT_array(bpy.types.Panel):
|
||||
row.operator("bim.add_array", icon="ADD", text="")
|
||||
|
||||
|
||||
class BIM_PT_stair(bpy.types.Panel):
|
||||
bl_label = "IFC Stair"
|
||||
bl_idname = "BIM_PT_stair"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "modifier"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# always display modifier if it's IFC object
|
||||
return tool.Ifc.get() and tool.Ifc.get_entity(context.active_object)
|
||||
|
||||
def draw(self, context):
|
||||
if not StairData.is_loaded:
|
||||
StairData.load()
|
||||
|
||||
props = context.active_object.BIMStairProperties
|
||||
|
||||
if StairData.data["parameters"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Stair", icon="IPO_CONSTANT")
|
||||
|
||||
stair_data = StairData.data["parameters"]["data"]
|
||||
box = self.layout.box()
|
||||
if props.is_editing != -1:
|
||||
row = box.row(align=True)
|
||||
row.operator("bim.finish_editing_stair", icon="CHECKMARK", text="Finish editing")
|
||||
row.operator("bim.cancel_editing_stair", icon="CANCEL", text="")
|
||||
row = box.row(align=True)
|
||||
for prop_name in props.get_props_kwargs():
|
||||
box.prop(props, prop_name)
|
||||
update_stair_modifier(context)
|
||||
else:
|
||||
row = box.row(align=True)
|
||||
row.label(text=f"Parameters:", icon="MOD_ARRAY")
|
||||
row.operator("bim.enable_editing_stair", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.remove_stair", icon="X", text="")
|
||||
row = box.row(align=True)
|
||||
for prop in props.get_props_kwargs():
|
||||
prop_value = stair_data[prop]
|
||||
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
||||
box.label(text=f"{props.bl_rna.properties[prop].name}: {prop_value}")
|
||||
|
||||
# calculated properties
|
||||
number_of_rises = props.number_of_treads + 1
|
||||
box.label(text=f"Number of risers: {number_of_rises}")
|
||||
box.label(text=f"Tread rise: {round(props.height / number_of_rises, 5)}")
|
||||
box.label(text=f"Length: {round(props.tread_run * number_of_rises, 5)}")
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.label(text="No Stair Found")
|
||||
row.operator("bim.add_stair", icon="ADD", text="")
|
||||
|
||||
|
||||
class BIM_MT_model(Menu):
|
||||
bl_idname = "BIM_MT_model"
|
||||
bl_label = "IFC Objects"
|
||||
|
||||
Reference in New Issue
Block a user