mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 17:57:02 +00:00
RailingData use refactor, solves #3416
This commit is contained in:
@@ -23,7 +23,6 @@ import blenderbim.tool as tool
|
|||||||
from blenderbim.bim.helper import prop_with_search
|
from blenderbim.bim.helper import prop_with_search
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
|
|
||||||
# from blenderbim.bim.module.model.data import AuthoringData, RailingData, RoofData
|
|
||||||
from blenderbim.bim.module.drawing.prop import ANNOTATION_TYPES_DATA
|
from blenderbim.bim.module.drawing.prop import ANNOTATION_TYPES_DATA
|
||||||
from blenderbim.bim.module.drawing.data import DecoratorData, AnnotationData
|
from blenderbim.bim.module.drawing.data import DecoratorData, AnnotationData
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
@@ -108,7 +107,6 @@ class LaunchAnnotationTypeManager(bpy.types.Operator):
|
|||||||
op.element = relating_type["id"]
|
op.element = relating_type["id"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AnnotationTool(WorkSpaceTool):
|
class AnnotationTool(WorkSpaceTool):
|
||||||
bl_space_type = "VIEW_3D"
|
bl_space_type = "VIEW_3D"
|
||||||
bl_context_mode = "OBJECT"
|
bl_context_mode = "OBJECT"
|
||||||
|
|||||||
@@ -364,17 +364,27 @@ class RailingData:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def load(cls):
|
def load(cls):
|
||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
cls.data = {"parameters": cls.parameters()}
|
cls.data = {}
|
||||||
|
cls.data["parameters"] = cls.pset_data()
|
||||||
|
cls.data["general_params"] = cls.general_params()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parameters(cls):
|
def pset_data(cls):
|
||||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
return tool.Model.get_railing_pset_data(bpy.context.active_object)
|
||||||
if element:
|
|
||||||
psets = ifcopenshell.util.element.get_psets(element)
|
@classmethod
|
||||||
parameters = psets.get("BBIM_Railing", None)
|
def general_params(cls):
|
||||||
if parameters:
|
props = bpy.context.active_object.BIMRailingProperties
|
||||||
parameters["data_dict"] = json.loads(parameters.get("Data", "[]") or "[]")
|
railing_data = cls.data["parameters"]["data_dict"]
|
||||||
return parameters
|
general_params = {}
|
||||||
|
general_props = props.get_general_kwargs(railing_type=railing_data["railing_type"])
|
||||||
|
for prop_name in general_props:
|
||||||
|
prop_value = railing_data[prop_name]
|
||||||
|
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
||||||
|
|
||||||
|
prop_readable_name = props.bl_rna.properties[prop_name].name
|
||||||
|
general_params[prop_readable_name] = prop_value
|
||||||
|
return general_params
|
||||||
|
|
||||||
|
|
||||||
class RoofData:
|
class RoofData:
|
||||||
|
|||||||
@@ -432,13 +432,13 @@ class BIMDoorProperties(PropertyGroup):
|
|||||||
name="Transom Thickness",
|
name="Transom Thickness",
|
||||||
description="Set values > 0 to add a transom.\n" "`0.050 mm` is good as default value",
|
description="Set values > 0 to add a transom.\n" "`0.050 mm` is good as default value",
|
||||||
default=0.000,
|
default=0.000,
|
||||||
subtype="DISTANCE"
|
subtype="DISTANCE",
|
||||||
)
|
)
|
||||||
transom_offset: bpy.props.FloatProperty(
|
transom_offset: bpy.props.FloatProperty(
|
||||||
name="Transom Offset",
|
name="Transom Offset",
|
||||||
description="Distance from the bottom door opening to the beginning of the transom (unlike windows)",
|
description="Distance from the bottom door opening to the beginning of the transom (unlike windows)",
|
||||||
default=1.525,
|
default=1.525,
|
||||||
subtype="DISTANCE"
|
subtype="DISTANCE",
|
||||||
)
|
)
|
||||||
|
|
||||||
casing_thickness: bpy.props.FloatProperty(
|
casing_thickness: bpy.props.FloatProperty(
|
||||||
@@ -547,7 +547,7 @@ class BIMRailingProperties(PropertyGroup):
|
|||||||
("NONE", "NONE", ""),
|
("NONE", "NONE", ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
is_editing: bpy.props.IntProperty(default=-1)
|
is_editing: bpy.props.BoolProperty(default=False)
|
||||||
is_editing_path: bpy.props.BoolProperty(default=False)
|
is_editing_path: bpy.props.BoolProperty(default=False)
|
||||||
|
|
||||||
railing_type: bpy.props.EnumProperty(name="Railing Type", items=railing_types, default="FRAMELESS_PANEL")
|
railing_type: bpy.props.EnumProperty(name="Railing Type", items=railing_types, default="FRAMELESS_PANEL")
|
||||||
@@ -567,25 +567,32 @@ class BIMRailingProperties(PropertyGroup):
|
|||||||
default=1.0,
|
default=1.0,
|
||||||
min=0.01,
|
min=0.01,
|
||||||
description="Distance between supports if automatic supports are used",
|
description="Distance between supports if automatic supports are used",
|
||||||
|
subtype="DISTANCE",
|
||||||
)
|
)
|
||||||
railing_diameter: bpy.props.FloatProperty(name="Railing Diameter", default=0.050)
|
railing_diameter: bpy.props.FloatProperty(name="Railing Diameter", default=0.050, subtype="DISTANCE")
|
||||||
clear_width: bpy.props.FloatProperty(
|
clear_width: bpy.props.FloatProperty(
|
||||||
name="Clear Width", default=0.040, description="Clear width between the railing and the wall"
|
name="Clear Width",
|
||||||
|
default=0.040,
|
||||||
|
description="Clear width between the railing and the wall",
|
||||||
|
subtype="DISTANCE",
|
||||||
)
|
)
|
||||||
terminal_type: bpy.props.EnumProperty(name="Terminal Type", items=cap_types, default="180")
|
terminal_type: bpy.props.EnumProperty(name="Terminal Type", items=cap_types, default="180")
|
||||||
|
|
||||||
def get_general_kwargs(self, convert_to_project_units=False):
|
def get_general_kwargs(self, railing_type=None, convert_to_project_units=False):
|
||||||
|
if railing_type is None:
|
||||||
|
railing_type = self.railing_type
|
||||||
|
|
||||||
base_kwargs = {
|
base_kwargs = {
|
||||||
"railing_type": self.railing_type,
|
"railing_type": railing_type,
|
||||||
"height": self.height,
|
"height": self.height,
|
||||||
}
|
}
|
||||||
additional_kwargs = {}
|
additional_kwargs = {}
|
||||||
if self.railing_type == "FRAMELESS_PANEL":
|
if railing_type == "FRAMELESS_PANEL":
|
||||||
additional_kwargs = {
|
additional_kwargs = {
|
||||||
"thickness": self.thickness,
|
"thickness": self.thickness,
|
||||||
"spacing": self.spacing,
|
"spacing": self.spacing,
|
||||||
}
|
}
|
||||||
elif self.railing_type == "WALL_MOUNTED_HANDRAIL":
|
elif railing_type == "WALL_MOUNTED_HANDRAIL":
|
||||||
additional_kwargs = {
|
additional_kwargs = {
|
||||||
"railing_diameter": self.railing_diameter,
|
"railing_diameter": self.railing_diameter,
|
||||||
"clear_width": self.clear_width,
|
"clear_width": self.clear_width,
|
||||||
@@ -606,6 +613,7 @@ class BIMRailingProperties(PropertyGroup):
|
|||||||
for prop_name in kwargs:
|
for prop_name in kwargs:
|
||||||
setattr(self, prop_name, kwargs[prop_name])
|
setattr(self, prop_name, kwargs[prop_name])
|
||||||
|
|
||||||
|
|
||||||
class BIMRoofProperties(PropertyGroup):
|
class BIMRoofProperties(PropertyGroup):
|
||||||
non_si_units_props = (
|
non_si_units_props = (
|
||||||
"is_editing",
|
"is_editing",
|
||||||
|
|||||||
@@ -23,14 +23,12 @@ import ifcopenshell
|
|||||||
from ifcopenshell.util.shape_builder import V
|
from ifcopenshell.util.shape_builder import V
|
||||||
import blenderbim
|
import blenderbim
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from blenderbim.bim.helper import convert_property_group_from_si
|
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.model.door import bm_sort_out_geom
|
from blenderbim.bim.module.model.door import bm_sort_out_geom
|
||||||
from blenderbim.bim.module.model.data import RailingData, refresh
|
from blenderbim.bim.module.model.data import RailingData, refresh
|
||||||
from blenderbim.bim.module.model.decorator import ProfileDecorator
|
from blenderbim.bim.module.model.decorator import ProfileDecorator
|
||||||
|
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector
|
||||||
from pprint import pprint
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# reference:
|
# reference:
|
||||||
@@ -38,7 +36,6 @@ import json
|
|||||||
# https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRailingType.htm
|
# https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRailingType.htm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def bm_split_edge_at_offset(edge, offset):
|
def bm_split_edge_at_offset(edge, offset):
|
||||||
v0, v1 = edge.verts
|
v0, v1 = edge.verts
|
||||||
|
|
||||||
@@ -83,7 +80,9 @@ def update_railing_modifier_ifc_data(context):
|
|||||||
|
|
||||||
if props.railing_type == "WALL_MOUNTED_HANDRAIL":
|
if props.railing_type == "WALL_MOUNTED_HANDRAIL":
|
||||||
body = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
|
body = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
|
||||||
railing_path = [Vector(v) for v in RailingData.data["parameters"]["data_dict"]["path_data"]["verts"]]
|
pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object)
|
||||||
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
|
railing_path = [Vector(v) for v in path_data["verts"]]
|
||||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||||
|
|
||||||
representation_data = {
|
representation_data = {
|
||||||
@@ -121,6 +120,7 @@ def update_railing_modifier_bmesh(context):
|
|||||||
obj = context.object
|
obj = context.object
|
||||||
props = obj.BIMRailingProperties
|
props = obj.BIMRailingProperties
|
||||||
|
|
||||||
|
# NOTE: using Data since bmesh update will hapen very often
|
||||||
if not RailingData.is_loaded:
|
if not RailingData.is_loaded:
|
||||||
RailingData.load()
|
RailingData.load()
|
||||||
path_data = RailingData.data["parameters"]["data_dict"]["path_data"]
|
path_data = RailingData.data["parameters"]["data_dict"]["path_data"]
|
||||||
@@ -317,7 +317,6 @@ class AddRailing(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
self.report({"ERROR"}, "Object has to be IfcRailing/IfcRailingType type to add a railing.")
|
self.report({"ERROR"}, "Object has to be IfcRailing/IfcRailingType type to add a railing.")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
|
||||||
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||||
path_data = get_path_data(obj)
|
path_data = get_path_data(obj)
|
||||||
if not path_data:
|
if not path_data:
|
||||||
@@ -353,7 +352,7 @@ class EnableEditingRailing(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
# required since we could load pset from .ifc and BIMRailingProperties won't be set
|
# required since we could load pset from .ifc and BIMRailingProperties won't be set
|
||||||
props.set_props_kwargs_from_ifc_data(data)
|
props.set_props_kwargs_from_ifc_data(data)
|
||||||
|
|
||||||
props.is_editing = 1
|
props.is_editing = True
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -381,7 +380,7 @@ class CancelEditingRailing(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
should_sync_changes_first=False,
|
should_sync_changes_first=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
props.is_editing = -1
|
props.is_editing = False
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -395,13 +394,12 @@ class FinishEditingRailing(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
props = obj.BIMRailingProperties
|
props = obj.BIMRailingProperties
|
||||||
|
|
||||||
if not RailingData.is_loaded:
|
pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object)
|
||||||
RailingData.load()
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
path_data = RailingData.data["parameters"]["data_dict"]["path_data"]
|
|
||||||
|
|
||||||
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||||
railing_data["path_data"] = path_data
|
railing_data["path_data"] = path_data
|
||||||
props.is_editing = -1
|
props.is_editing = False
|
||||||
|
|
||||||
update_bbim_railing_pset(element, railing_data)
|
update_bbim_railing_pset(element, railing_data)
|
||||||
update_railing_modifier_ifc_data(context)
|
update_railing_modifier_ifc_data(context)
|
||||||
@@ -419,9 +417,8 @@ class FlipRailingPathOrder(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
props = obj.BIMRailingProperties
|
props = obj.BIMRailingProperties
|
||||||
|
|
||||||
if not RailingData.is_loaded:
|
pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object)
|
||||||
RailingData.load()
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
path_data = RailingData.data["parameters"]["data_dict"]["path_data"]
|
|
||||||
|
|
||||||
# flip the vertex order and edges
|
# flip the vertex order and edges
|
||||||
path_data["verts"] = path_data["verts"][::-1]
|
path_data["verts"] = path_data["verts"][::-1]
|
||||||
@@ -497,7 +494,9 @@ class FinishEditingRailingPath(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
props.is_editing_path = False
|
props.is_editing_path = False
|
||||||
|
|
||||||
update_bbim_railing_pset(element, railing_data)
|
update_bbim_railing_pset(element, railing_data)
|
||||||
refresh() # RailingData has to be updated before run update_railing_modifier_bmesh
|
# RailingData has to be updated before run update_railing_modifier_bmesh
|
||||||
|
# since we know that BBIM_Railing could have changed
|
||||||
|
refresh()
|
||||||
update_railing_modifier_bmesh(context)
|
update_railing_modifier_bmesh(context)
|
||||||
if bpy.context.object.mode == "EDIT":
|
if bpy.context.object.mode == "EDIT":
|
||||||
bpy.ops.object.mode_set(mode="OBJECT")
|
bpy.ops.object.mode_set(mode="OBJECT")
|
||||||
@@ -512,9 +511,8 @@ class RemoveRailing(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
props = obj.BIMRailingProperties
|
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
obj.BIMRailingProperties.is_editing = -1
|
obj.BIMRailingProperties.is_editing = False
|
||||||
|
|
||||||
pset = tool.Pset.get_element_pset(element, "BBIM_Railing")
|
pset = tool.Pset.get_element_pset(element, "BBIM_Railing")
|
||||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||||
|
|||||||
@@ -552,9 +552,7 @@ class BIM_PT_railing(bpy.types.Panel):
|
|||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text="Railing parameters", icon="OUTLINER_OB_LATTICE")
|
row.label(text="Railing parameters", icon="OUTLINER_OB_LATTICE")
|
||||||
|
|
||||||
railing_data = RailingData.data["parameters"]["data_dict"]
|
if props.is_editing:
|
||||||
|
|
||||||
if props.is_editing != -1:
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.operator("bim.finish_editing_railing", icon="CHECKMARK", text="Finish Editing")
|
row.operator("bim.finish_editing_railing", icon="CHECKMARK", text="Finish Editing")
|
||||||
row.operator("bim.cancel_editing_railing", icon="CANCEL", text="")
|
row.operator("bim.cancel_editing_railing", icon="CANCEL", text="")
|
||||||
@@ -577,18 +575,15 @@ class BIM_PT_railing(bpy.types.Panel):
|
|||||||
else:
|
else:
|
||||||
row.operator("bim.enable_editing_railing", icon="GREASEPENCIL", text="")
|
row.operator("bim.enable_editing_railing", icon="GREASEPENCIL", text="")
|
||||||
row.operator("bim.enable_editing_railing_path", icon="ANIM", text="")
|
row.operator("bim.enable_editing_railing_path", icon="ANIM", text="")
|
||||||
# TODO: good for preview but probably should move to .is_editing == -1
|
# TODO: good for preview but probably should move to .is_editing == True
|
||||||
# since it's writing to ifc
|
# since it's writing to ifc
|
||||||
row.operator("bim.flip_railing_path_order", icon="ARROW_LEFTRIGHT", text="")
|
row.operator("bim.flip_railing_path_order", icon="ARROW_LEFTRIGHT", text="")
|
||||||
row.operator("bim.remove_railing", icon="X", text="")
|
row.operator("bim.remove_railing", icon="X", text="")
|
||||||
|
|
||||||
box = self.layout.box()
|
box = self.layout.box()
|
||||||
general_props = props.get_general_kwargs()
|
for prop_name, prop_value in RailingData.data["general_params"].items():
|
||||||
for prop in general_props:
|
|
||||||
prop_value = railing_data[prop]
|
|
||||||
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
row.label(text=f"{props.bl_rna.properties[prop].name}")
|
row.label(text=prop_name)
|
||||||
row.label(text=str(prop_value))
|
row.label(text=str(prop_value))
|
||||||
else:
|
else:
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from blenderbim.bim import import_ifc
|
|||||||
from blenderbim.bim.module.geometry.helper import Helper
|
from blenderbim.bim.module.geometry.helper import Helper
|
||||||
import collections
|
import collections
|
||||||
from blenderbim.bim.module.model.data import AuthoringData
|
from blenderbim.bim.module.model.data import AuthoringData
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class Model(blenderbim.core.tool.Model):
|
class Model(blenderbim.core.tool.Model):
|
||||||
@@ -734,3 +735,15 @@ class Model(blenderbim.core.tool.Model):
|
|||||||
obj.preview.image_pixels_float = pixels
|
obj.preview.image_pixels_float = pixels
|
||||||
|
|
||||||
AuthoringData.type_thumbnails[element.id()] = obj.preview.icon_id
|
AuthoringData.type_thumbnails[element.id()] = obj.preview.icon_id
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_railing_pset_data(cls, object):
|
||||||
|
element = tool.Ifc.get_entity(object)
|
||||||
|
if not element:
|
||||||
|
return
|
||||||
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
|
pset_data = psets.get("BBIM_Railing", None)
|
||||||
|
if not pset_data:
|
||||||
|
return
|
||||||
|
pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]")
|
||||||
|
return pset_data
|
||||||
|
|||||||
Reference in New Issue
Block a user